ptos: ke: Add per-processor scheduler queue + PBI packer
Signed-off-by: Chloe M <chloe@mensia.org>
This commit is contained in:
@@ -9,9 +9,15 @@ set -e
|
||||
ISO=$PT_PROJECT_ROOT/artifacts/ptos.iso
|
||||
CONFIG=$PT_PROJECT_ROOT/service/base/boot/limine.conf
|
||||
KERNEL=$PT_PROJECT_ROOT/artifacts/ptsv.sys
|
||||
HOLE=$PT_PROJECT_ROOT/service/host/bin/hole
|
||||
|
||||
mkdir -p iso_root/boot/
|
||||
|
||||
# Create the pre-boot image (PBI)
|
||||
pushd ../base
|
||||
$HOLE -f . -o ../boot/iso_root/boot/pbi.hole
|
||||
popd
|
||||
|
||||
# Copy the kernel to the ISO root
|
||||
cp $KERNEL iso_root/boot
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
/bin
|
||||
@@ -0,0 +1,21 @@
|
||||
#
|
||||
# Copyright (c) 2026, Chloe M.
|
||||
# Provided under the BSD-3 clause
|
||||
#
|
||||
# Description: Host tools build
|
||||
# Author: Chloe M.
|
||||
#
|
||||
|
||||
.SILENT:
|
||||
|
||||
.PHONY: all
|
||||
all: bin hole
|
||||
|
||||
.PHONY: bin
|
||||
bin:
|
||||
mkdir -p $@
|
||||
|
||||
.PHONY: hole
|
||||
hole:
|
||||
echo "[*] Building hole..."
|
||||
cd hole/; $(MAKE)
|
||||
@@ -0,0 +1,29 @@
|
||||
#
|
||||
# Copyright (c) 2026, Chloe M.
|
||||
# Provided under the BSD-3 clause
|
||||
#
|
||||
# Description: PBI boot packer build script
|
||||
# Author: Chloe M.
|
||||
#
|
||||
|
||||
.SILENT:
|
||||
PROMPT := printf "%s\t\t%s\n"
|
||||
|
||||
CC = gcc
|
||||
CFILES = $(shell find . -name "*.c")
|
||||
OFILES = $(CFILES:.c=.o)
|
||||
|
||||
CFLAGS = \
|
||||
-Wall \
|
||||
-pedantic
|
||||
|
||||
.PHONY: all
|
||||
all: ../bin/hole
|
||||
|
||||
.PHONY: hole
|
||||
../bin/hole: $(OFILES)
|
||||
$(CC) $^ -o $@
|
||||
|
||||
%.o: %.c
|
||||
$(PROMPT) "CC" $<
|
||||
$(CC) -c $(CFLAGS) $< -o $@
|
||||
@@ -0,0 +1,347 @@
|
||||
/*
|
||||
* Copyright (c) 2026, Chloe M.
|
||||
* Provided under the BSD-3 clause.
|
||||
*
|
||||
* Description: pre-boot image format packer
|
||||
* Author: Chloe M.
|
||||
*/
|
||||
|
||||
#define _DEFAULT_SOURCE
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/queue.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <dirent.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define REF_MAGIC "PTOS.PBI"
|
||||
#define REF_MAGIC_LEN 8
|
||||
#define REF_PATH_LEN 256
|
||||
|
||||
/* Set to 1 for verbose */
|
||||
#define DEBUG 0
|
||||
|
||||
#if DEBUG
|
||||
#define DTRACE(fmt, ...) printf(fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define DTRACE(...) (void)0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* A reference is an entry within the table that refers
|
||||
* to a block of data after the reference table.
|
||||
*
|
||||
* @magic: Reference magic
|
||||
* @path: File path
|
||||
* @size: File size
|
||||
* @data_off: Data offset
|
||||
* @real_path: Real path
|
||||
* @link: Queue link
|
||||
*
|
||||
* XXX: Do not reorder anything ABOVE 'link'
|
||||
*/
|
||||
struct hole_ref {
|
||||
char magic[REF_MAGIC_LEN];
|
||||
char path[REF_PATH_LEN];
|
||||
size_t size;
|
||||
off_t data_off;
|
||||
char *real_path;
|
||||
TAILQ_ENTRY(hole_ref) link;
|
||||
};
|
||||
|
||||
/* Globals */
|
||||
static bool output_override = false;
|
||||
static char *output_path = "out.hole";
|
||||
static char *fill_dirpath = NULL;
|
||||
static size_t file_count = 0;
|
||||
static TAILQ_HEAD(, hole_ref) hole_files;
|
||||
|
||||
/*
|
||||
* Display the help options
|
||||
*/
|
||||
static void
|
||||
help(void)
|
||||
{
|
||||
printf("usage: ./hole [flags]\n");
|
||||
printf("[-h] Display this help menu\n");
|
||||
printf("[-f] Fill hole with directory\n");
|
||||
printf("[-o] Output blob path\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy the hole files table
|
||||
*/
|
||||
static void
|
||||
hole_files_destroy(void)
|
||||
{
|
||||
struct hole_ref *ref, *tmp;
|
||||
|
||||
while ((ref = TAILQ_FIRST(&hole_files)) != NULL) {
|
||||
DTRACE("delete %s\n", ref->real_path);
|
||||
free(ref->real_path);
|
||||
|
||||
tmp = ref;
|
||||
TAILQ_REMOVE(&hole_files, ref, link);
|
||||
free(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Used to fix up offsets after
|
||||
*/
|
||||
static void
|
||||
hole_table_fixup(void)
|
||||
{
|
||||
struct stat sb;
|
||||
struct hole_ref *ref;
|
||||
size_t table_end, offset;
|
||||
size_t hdr_size;
|
||||
|
||||
hdr_size = sizeof(struct hole_ref);
|
||||
hdr_size -= sizeof(ref->real_path);
|
||||
hdr_size -= sizeof(ref->link);
|
||||
table_end = file_count * hdr_size;
|
||||
offset = table_end;
|
||||
|
||||
printf("* fixing up offsets...\n");
|
||||
printf("* table end @ %zx\n", table_end);
|
||||
|
||||
TAILQ_FOREACH(ref, &hole_files, link) {
|
||||
if (stat(ref->real_path, &sb) < 0) {
|
||||
perror("stat");
|
||||
continue;
|
||||
}
|
||||
|
||||
ref->size = sb.st_size;
|
||||
ref->data_off = offset;
|
||||
|
||||
DTRACE("data_off=%zx\n", ref->data_off);
|
||||
offset += ref->size;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
blob_write(void)
|
||||
{
|
||||
struct hole_ref *ref;
|
||||
int fd, ffd;
|
||||
void *data;
|
||||
size_t fsize, hdr_len;
|
||||
|
||||
fd = open(output_path, O_RDWR | O_CREAT | O_TRUNC, 0777);
|
||||
if (fd < 0) {
|
||||
perror("open");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* PASS 1):
|
||||
* We are to write the header of each file into the
|
||||
* top of the blob.
|
||||
*/
|
||||
TAILQ_FOREACH(ref, &hole_files, link) {
|
||||
hdr_len = sizeof(*ref);
|
||||
hdr_len -= sizeof(ref->real_path);
|
||||
hdr_len -= sizeof(ref->link);
|
||||
write(fd, ref, hdr_len);
|
||||
}
|
||||
|
||||
/*
|
||||
* PASS 2):
|
||||
* Now we can write the contents of each file after
|
||||
*/
|
||||
TAILQ_FOREACH(ref, &hole_files, link) {
|
||||
ffd = open(ref->real_path, O_RDONLY);
|
||||
if (ffd < 0) {
|
||||
perror("open[ffd]");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Obtain the file size */
|
||||
fsize = lseek(ffd, 0, SEEK_END);
|
||||
lseek(ffd, 0, SEEK_SET);
|
||||
|
||||
data = mmap(
|
||||
NULL,
|
||||
fsize,
|
||||
PROT_READ,
|
||||
MAP_SHARED,
|
||||
ffd,
|
||||
0
|
||||
);
|
||||
|
||||
if (data == NULL) {
|
||||
close(ffd);
|
||||
perror("mmap");
|
||||
continue;
|
||||
}
|
||||
|
||||
lseek(fd, SEEK_SET, ref->data_off);
|
||||
write(fd, data, fsize);
|
||||
munmap(data, fsize);
|
||||
close(ffd);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Strip a path of leading '.' and '/' characters
|
||||
*
|
||||
* @path: Path to strip
|
||||
*/
|
||||
static const char *
|
||||
path_strip(const char *path)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
if (path == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p = path;
|
||||
while (*p == '.' || *p == '/') {
|
||||
++p;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
* Push a file to the hole files table
|
||||
*/
|
||||
static int
|
||||
push_file(const char *path)
|
||||
{
|
||||
struct hole_ref *ref;
|
||||
const char *stripped;
|
||||
|
||||
if (path == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ref = malloc(sizeof(*ref));
|
||||
if (ref == NULL) {
|
||||
printf("fatal: could not allocate ref\n");
|
||||
hole_files_destroy();
|
||||
return -1;
|
||||
}
|
||||
|
||||
ref->real_path = strdup(path);
|
||||
stripped = path_strip(path);
|
||||
|
||||
memcpy(ref->magic, REF_MAGIC, sizeof(REF_MAGIC));
|
||||
memcpy(ref->path, stripped, strlen(stripped) + 1);
|
||||
ref->data_off = 0;
|
||||
|
||||
TAILQ_INSERT_TAIL(&hole_files, ref, link);
|
||||
++file_count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan a directory to fill the blob
|
||||
*/
|
||||
static void
|
||||
scan_dir(const char *path)
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *dirent;
|
||||
char pathbuf[300];
|
||||
|
||||
if (path == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
dir = opendir(path);
|
||||
if (dir == NULL) {
|
||||
perror("opendir");
|
||||
return;
|
||||
}
|
||||
|
||||
while ((dirent = readdir(dir)) != NULL) {
|
||||
if (dirent->d_name[0] == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
snprintf(pathbuf, sizeof(pathbuf), "%s/%s", path, dirent->d_name);
|
||||
switch (dirent->d_type) {
|
||||
case DT_REG:
|
||||
printf("[f] %s\n", pathbuf);
|
||||
if (push_file(pathbuf) < 0) {
|
||||
free(fill_dirpath);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case DT_DIR:
|
||||
printf("[d] %s\n", pathbuf);
|
||||
scan_dir(pathbuf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int opt;
|
||||
|
||||
if (argc < 2) {
|
||||
printf("fatal: too few arguments\n");
|
||||
help();
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((opt = getopt(argc, argv, "hf:o:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
help();
|
||||
return -1;
|
||||
case 'f':
|
||||
fill_dirpath = strdup(optarg);
|
||||
if (fill_dirpath == NULL) {
|
||||
printf("fatal: out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
case 'o':
|
||||
output_override = true;
|
||||
output_path = strdup(optarg);
|
||||
if (output_path == NULL) {
|
||||
printf("fatal: out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fill_dirpath == NULL) {
|
||||
printf("fatal: expected fill directory for blob...\n");
|
||||
help();
|
||||
return -1;
|
||||
}
|
||||
|
||||
TAILQ_INIT(&hole_files);
|
||||
scan_dir(fill_dirpath);
|
||||
|
||||
hole_table_fixup();
|
||||
blob_write();
|
||||
|
||||
hole_files_destroy();
|
||||
free(fill_dirpath);
|
||||
|
||||
if (output_override) {
|
||||
free(output_path);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -88,4 +88,7 @@ HalKpcrP2Init(KPCR *Kpcr)
|
||||
: "i" (GDT_TSS)
|
||||
: "memory"
|
||||
);
|
||||
|
||||
/* Initialize the scheduler queue */
|
||||
SCHED_QUEUE_INIT(&Kpcr->SchedQueue);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <ptdef.h>
|
||||
#include <ex/pool.h>
|
||||
#include <ke/sched.h>
|
||||
#include <machine/mcb.h>
|
||||
|
||||
/*
|
||||
@@ -19,11 +20,13 @@
|
||||
*
|
||||
* @Id: Logical processor ID assigned by us
|
||||
* @PoolRegion: Allocator pool region
|
||||
* @SchedQueue: Per-core scheduler queue
|
||||
* @Mcb: Machine core block
|
||||
*/
|
||||
typedef struct {
|
||||
USHORT Id;
|
||||
POOL_REGION PoolRegion;
|
||||
SCHED_QUEUE SchedQueue;
|
||||
MCB Mcb;
|
||||
} KPCR;
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2026, Chloe M.
|
||||
* Provided under the BSD-3 clause.
|
||||
*
|
||||
* Description: Scheduler management
|
||||
* Author: Chloe M.
|
||||
*/
|
||||
|
||||
#ifndef _KE_SCHED_H_
|
||||
#define _KE_SCHED_H_ 1
|
||||
|
||||
#include <ps/thread.h>
|
||||
#include <ptdef.h>
|
||||
#include <queue.h>
|
||||
|
||||
/*
|
||||
* Represents a scheduler queue that threads can be pulled
|
||||
* from and added to.
|
||||
*
|
||||
* @ThreadQueue: Represents the actual queue that holds threads
|
||||
* @QueueEntries: Represents the number of entries in the queue
|
||||
*/
|
||||
typedef struct {
|
||||
TAILQ_HEAD(, _THREAD) ThreadQueue;
|
||||
USIZE QueueEntries;
|
||||
} SCHED_QUEUE;
|
||||
|
||||
/* Macro used to initialize the scheduler queue */
|
||||
#define SCHED_QUEUE_INIT(SQ_P) \
|
||||
TAILQ_INIT(&(SQ_P)->ThreadQueue); \
|
||||
(SQ_P)->QueueEntries = 0;
|
||||
|
||||
#endif /* !_KE_SCHED_H_ */
|
||||
Reference in New Issue
Block a user