Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 42 additions & 12 deletions include/kernel/proc/process.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <kernel/sched/thread.h>
#include <kernel/sched/wait.h>
#include <kernel/sync/futex.h>
#include <kernel/sync/rcu.h>
#include <kernel/utils/map.h>
#include <kernel/utils/ref.h>

Expand Down Expand Up @@ -45,8 +46,9 @@ typedef enum
*/
typedef struct
{
tid_t newTid;
list_t list;
_Atomic(tid_t) newTid;
list_t list; ///< Reads are RCU protected, writes require the lock.
uint64_t count;
lock_t lock;
} process_threads_t;

Expand Down Expand Up @@ -94,8 +96,16 @@ typedef struct process
char** argv;
uint64_t argc;
group_member_t group;
rcu_entry_t rcu;
} process_t;

/**
* @brief Global list of all processes.
*
* @warning Should only be read while in a RCU read-side critical section.
*/
extern list_t _processes;

/**
* @brief Allocates and initializes a new process.
*
Expand Down Expand Up @@ -184,29 +194,49 @@ void process_kill(process_t* process, const char* status);
void process_remove(process_t* process);

/**
* @brief Gets the first process in the system for iteration.
* @brief Gets the first thread of a process.
*
* @return A reference to the first process, or `NULL` if there are no processes.
* @warning Must be used within a RCU read-side critical section.
*
* @param process The process to get the first thread of.
* @return The first thread of the process, or `NULL` if the process has no threads.
*/
process_t* process_iterate_begin(void);
static inline thread_t* process_rcu_first_thread(process_t* process)
{
return CONTAINER_OF_SAFE(list_first(&process->threads.list), thread_t, processEntry);
}

/**
* @brief Gets the next process in the system for iteration.
* @brief Gets the amount of threads in a process.
*
* @warning Must be used within a RCU read-side critical section.
*
* @param process The process to get the thread amount of.
* @return The amount of threads in the process.
*/
static inline uint64_t process_rcu_thread_count(process_t* process)
{
return process->threads.count;
}

/**
* @brief Macro to iterate over all threads in a process.
*
* @warning Must be used within a RCU read-side critical section.
*
* @param prev The current process in the iteration, will be unreferenced.
* @return A reference to the next process, or `NULL` if there are no more processes.
* @param thread Loop variable, a pointer to `thread_t`.
* @param process The process to iterate the threads of.
*/
process_t* process_iterate_next(process_t* prev);
#define PROCESS_RCU_THREAD_FOR_EACH(thread, process) LIST_FOR_EACH(thread, &(process)->threads.list, processEntry)

/**
* @brief Macro to iterate over all processes.
*
* @note If the loop is exited early the `process` variable must be unreferenced.
* @warning Must be used within a RCU read-side critical section.
*
* @param process Loop variable, a pointer to `process_t`.
*/
#define PROCESS_FOR_EACH(process) \
for ((process) = process_iterate_begin(); (process) != NULL; (process) = process_iterate_next(process))
#define PROCESS_RCU_FOR_EACH(process) LIST_FOR_EACH(process, &_processes, entry)

/**
* @brief Sets the command line arguments for a process.
Expand Down
16 changes: 9 additions & 7 deletions include/kernel/sched/thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <kernel/ipc/note.h>
#include <kernel/sched/sched.h>
#include <kernel/sched/wait.h>
#include <kernel/sync/rcu.h>
#include <kernel/utils/ref.h>

#include <sys/list.h>
Expand Down Expand Up @@ -77,6 +78,7 @@ typedef struct thread
note_queue_t notes;
syscall_ctx_t syscall;
perf_thread_ctx_t perf;
rcu_entry_t rcu;
/**
* The threads interrupt frame is used to save the values in the CPU registers such that the scheduler can continue
* executing the thread later on.
Expand All @@ -94,6 +96,13 @@ typedef struct thread
*/
thread_t* thread_new(process_t* process);

/**
* @brief Frees a thread structure.
*
* @param thread The thread to be freed.
*/
void thread_free(thread_t* thread);

/**
* @brief Kernel thread entry point function type.
*/
Expand All @@ -108,13 +117,6 @@ typedef void (*thread_kernel_entry_t)(void* arg);
*/
tid_t thread_kernel_create(thread_kernel_entry_t entry, void* arg);

/**
* @brief Frees a thread structure.
*
* @param thread The thread to be freed.
*/
void thread_free(thread_t* thread);

/**
* @brief Retrieves the currently running thread.
*
Expand Down
17 changes: 10 additions & 7 deletions src/kernel/fs/procfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@
#include <kernel/fs/vfs.h>
#include <kernel/log/log.h>
#include <kernel/log/panic.h>
#include <kernel/proc/process.h>
#include <kernel/sched/sched.h>
#include <kernel/sched/thread.h>
#include <kernel/sync/lock.h>

#include <assert.h>
#include <errno.h>
#include <kernel/sync/rcu.h>
#include <stdatomic.h>
#include <stdlib.h>
#include <string.h>
Expand Down Expand Up @@ -250,9 +252,9 @@ static size_t procfs_note_write(file_t* file, const void* buffer, size_t count,

process_t* process = file->inode->private;

LOCK_SCOPE(&process->threads.lock);
RCU_READ_SCOPE();

thread_t* thread = CONTAINER_OF_SAFE(list_first(&process->threads.list), thread_t, processEntry);
thread_t* thread = process_rcu_first_thread(process);
if (thread == NULL)
{
errno = EINVAL;
Expand Down Expand Up @@ -384,9 +386,9 @@ static size_t procfs_perf_read(file_t* file, void* buffer, size_t count, size_t*
process_t* process = file->inode->private;
size_t userPages = space_user_page_count(&process->space);

lock_acquire(&process->threads.lock);
size_t threadCount = list_size(&process->threads.list);
lock_release(&process->threads.lock);
RCU_READ_SCOPE();

size_t threadCount = process_rcu_thread_count(process);

clock_t userClocks = atomic_load(&process->perf.userClocks);
clock_t kernelClocks = atomic_load(&process->perf.kernelClocks);
Expand Down Expand Up @@ -1206,8 +1208,10 @@ static uint64_t procfs_iterate(dentry_t* dentry, dir_ctx_t* ctx)
}
}

RCU_READ_SCOPE();

process_t* process;
PROCESS_FOR_EACH(process)
PROCESS_RCU_FOR_EACH(process)
{
if (ctx->index++ < ctx->pos)
{
Expand All @@ -1218,7 +1222,6 @@ static uint64_t procfs_iterate(dentry_t* dentry, dir_ctx_t* ctx)
snprintf(name, sizeof(name), "%llu", process->id);
if (!ctx->emit(ctx, name, ino_gen(dentry->inode->number, name), INODE_DIR))
{
UNREF(process);
return 0;
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/kernel/proc/group.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include <errno.h>
#include <kernel/sync/lock.h>
#include <kernel/sync/rcu.h>
#include <stdlib.h>

static void group_free(group_t* group)
Expand Down Expand Up @@ -158,9 +159,9 @@ uint64_t group_send_note(group_member_t* member, const char* note)
process_t* process;
LIST_FOR_EACH(process, &group->processes, group.entry)
{
LOCK_SCOPE(&process->threads.lock);
RCU_READ_SCOPE();

thread_t* thread = CONTAINER_OF_SAFE(list_first(&process->threads.list), thread_t, processEntry);
thread_t* thread = process_rcu_first_thread(process);
if (thread == NULL)
{
continue;
Expand Down
Loading