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
2 changes: 2 additions & 0 deletions include/kernel/arch/i686/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

#include <kernel/types.h>

#include <dailyrun/arch/i686/cpu.h>

#include <utils/bits.h>
#include <utils/compiler.h>
#include <utils/map.h>
Expand Down
27 changes: 7 additions & 20 deletions include/kernel/arch/i686/interrupts.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include <kernel/types.h>

#include <kernel/arch/i686/gdt.h>
#include <kernel/arch/i686/cpu.h>

#include <utils/compiler.h>

Expand Down Expand Up @@ -116,31 +117,17 @@ typedef struct PACKED idt_descriptor {
/** @brief Frame passed onto the interrupt handlers by our stub handler */
struct interrupt_frame {

/**
* @brief Dump of the process's registers.
* These are pushed by `pusha` inside our stub handler
*/
struct registers_dump {
u32 edi, esi, ebp, esp;
u32 ebx, edx, ecx, eax;
} stub;
/** Snapshot of the registers at the time the interrupt happened.*/
struct x86_regs regs;

/** Interrupt number (pushed by our stub) */
/** Error code and interrupt number (pushed by our stub) */
u32 nr;
/** Error code for this exception (pushed by our stub) */
u32 error;

/**
* @brief Default x86 interrupt frame pushed by the cpu
* @ref Intel developper manual, figure 6-4
/*
* The interrupt frame pushed by the hardware starts here.
*/
struct cpu_interrupt_frame {
u32 eip;
u32 cs;
u32 flags;
u32 esp;
u32 ss;
} state;
struct x86_interrupt_frame frame;
};

static ALWAYS_INLINE void arch_interrupts_disable(void)
Expand Down
6 changes: 3 additions & 3 deletions include/kernel/arch/i686/process.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,12 @@ static inline void *arch_thread_get_stack_pointer(thread_context_t *ctx)
static inline void
arch_thread_set_base_pointer(thread_context_t *ctx, void *ptr)
{
ctx->frame.stub.ebp = (vaddr_t)ptr;
ctx->frame.regs.ebp = (vaddr_t)ptr;
}

static inline void *arch_thread_get_base_pointer(thread_context_t *ctx)
{
return (void *)ctx->frame.stub.ebp;
return (void *)ctx->frame.regs.ebp;
}

static inline void
Expand Down Expand Up @@ -113,7 +113,7 @@ static inline void *arch_thread_get_user_stack_top(const thread_context_t *ctx)
static inline void *
arch_thread_get_interrupt_return_address(const thread_context_t *ctx)
{
return (void *)ctx->frame.state.eip;
return (void *)ctx->frame.frame.eip;
}

#endif /* KERNEL_ARCH_I686_PROCESS_H */
6 changes: 6 additions & 0 deletions include/kernel/arch/i686/signal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef KERNEL_ARCH_I686_SIGNAL_H
#define KERNEL_ARCH_I686_SIGNAL_H

#include <dailyrun/arch/i686/signal.h>

#endif /* KERNEL_ARCH_I686_SIGNAL_H */
8 changes: 8 additions & 0 deletions include/kernel/interrupts.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,14 @@ static inline void scope_irq_off_destructor(scope_irq_off_t *guard)
scope_irq_off_constructor(); \
!guard.done; guard.done = true)


/*
* Generic interrupt handlers.
*/

extern struct interrupt_handler division_by_zero;
extern struct interrupt_handler invalid_instruction;

/** @} */

#endif /* KERNEL_INTERRUPTS_H */
67 changes: 59 additions & 8 deletions include/kernel/process.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <kernel/types.h>
#include <kernel/user.h>
#include <kernel/vmm.h>
#include <kernel/signal.h>

#include <libalgo/linked_list.h>
#include <utils/compiler.h>
Expand Down Expand Up @@ -85,12 +86,16 @@ typedef enum thread_state {
struct process {
char name[PROCESS_NAME_MAX_LEN]; /*!< The thread's name */
pid_t pid; /*!< Process' unique ID */
unsigned int flags;

struct address_space *as; /*!< The process's address space */

struct process *parent;
llist_t threads; /*!< Linked list of the process' active threads */
llist_t children; /*!< Linked list of the process' active children */
node_t this; /*< Node inside the parent's list of children */

node_t this; /*!< Node inside the parent's list of children */
node_t this_global; /*!< Used by the global list of alive processes */

size_t refcount; /*!< Reference count to this process.
We only kill a process once all of its threads have
Expand All @@ -104,14 +109,31 @@ struct process {
struct file *files[PROCESS_FD_COUNT];
spinlock_t files_lock; /*!< Lock for @ref open_files */

/*
* Signal handling.
*/
struct signal_set *sig_set; /* Registered signal handlers. */
struct signal_queue sig_pending;
sig_sa_sigaction_t sig_handler; /* stub handler set by sigsethandler(). */

thread_state_t state;
uint8_t exit_status; /** Transmitted to the parent process during wait() */
uint16_t exit_status; /** Transmitted to the parent process during wait() */

struct user_creds *creds; /** Process credentials. */

spinlock_t lock;
};

/*
* Possible values for (struct process)->flags.
*/
enum process_flags {
PROC_SA_NOCLDWAIT = BIT(0), /* Do not generate SIGCHLD when children stop */
};

/* Union of all the flags that should be inherited when forking. */
#define PROC_FLAGS_INHERITED (PROC_SA_NOCLDWAIT)

/**
* @brief A single thread.
*
Expand All @@ -135,13 +157,14 @@ typedef struct thread {
thread_context_t context;
thread_state_t state; /*!< Thread's current state, used by the scheduler */

struct process *process; /*!< Containing process */
node_t proc_this; /*!< Linked list used by the process to list threads */

pid_t tid; /*!< Thread ID */
u32 flags; /*!< Combination of \ref thread_flags values */

node_t this; /*!< Intrusive linked list used by the scheduler */
struct process *process; /*!< Containing process */

node_t this_proc; /*!< Used by a process to list threads */
node_t this_sched; /*!< Used by the scheduler */
node_t this_global; /*!< Used by the global list of alive processes */

/** Information relative to the current state of the thread */
union {
Expand All @@ -151,8 +174,25 @@ typedef struct thread {
} sleep;
};

/*
* Signal handling.
*/
struct signal_queue sig_pending;
sigset_t sig_blocked; /* mask of currently blocked signals. */

} thread_t;

/*
* List of all processes and threads currently alive.
*
* These list only contain live threads/processes so that lookups
* do not return objects that have already been killed.
*/
extern llist_t processes_list;
extern spinlock_t processes_list_lock;
extern llist_t threads_list;
extern spinlock_t threads_list_lock;

/** @enum thread_flags */
typedef enum thread_flags {
THREAD_KERNEL = BIT(0), ///< This is a kernel thread
Expand Down Expand Up @@ -294,6 +334,9 @@ extern struct process *init_process;
*/
void process_init_kernel_process(void);

/** Kill a process. */
void process_kill(struct process *process, uint16_t status);

/** Register an open file inside the process's open file descriptor table.
* @return The registered file's index inside the open file descriptor table.
*/
Expand Down Expand Up @@ -332,6 +375,9 @@ static inline void process_set_name(struct process *process, const char *name,
strlcpy(process->name, name, MIN(size + 1, PROCESS_NAME_MAX_LEN));
}

/** Find an **alive** process by its PID. */
struct process *process_find_by_pid(pid_t pid);

/** The currently running thread */
extern thread_t *current;

Expand Down Expand Up @@ -403,8 +449,13 @@ void thread_kill(thread_t *);
*/
struct thread *thread_fork(struct thread *, thread_entry_t, void *);

/** @defgroup arch_process Processes - arch specifics
* @ingroup x86_process
/** Try and deliver the first non-blocked pending signal.
*
* This function should be called before returning to userland.
*/
void thread_deliver_pending_signal(struct thread *thread);

/** Find an **alive** thread by its TID. */
struct thread *thread_find_by_tid(pid_t tid);

/** @} */
120 changes: 120 additions & 0 deletions include/kernel/signal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
* Posix signals
*
* Reference:
* * POSIX 2.4 - Signal Concepts
*/

#ifndef KERNEL_SIGNAL_H
#define KERNEL_SIGNAL_H

#include <kernel/spinlock.h>
#include <kernel/atomic.h>
#include <kernel/error.h>

#include <libalgo/queue.h>

#include <sys/signal.h>

#if ARCH == i686
#include <kernel/arch/i686/signal.h>
#endif

struct thread;
struct process;

#define SIGNAL_MIN 1
#define SIGNAL_MAX (SIGNAL_COUNT - 1)
#define SIGNAL_COUNT NSIG

/*
* A pending signal.
*
* This struct holds information about a pending signals that is necessary
* to take decisions and fill the structures during signal delivery.
*/
struct signal_context {
node_t this; /* used by struct signal_queue */
siginfo_t si_info;
int si_signo;
};

/*
* A queue of pending signals.
*
* There exists one queue of pending signal per process AND per thread.
*/
struct signal_queue {
spinlock_t lock;
llist_t signals; /* struct signal_context */
sigset_t pending;
};

static inline void signal_queue_init(struct signal_queue *queue)
{
INIT_SPINLOCK(queue->lock);
INIT_LLIST(queue->signals);
}

/*
* Reflects what is specified in sigaction().
*/
struct signal_action {
struct sigaction sa_action;
};

/*
*
*/
struct signal_set {
spinlock_t lock; /* should be held when accessing this structure. */
struct signal_action sig_actions[SIGNAL_COUNT];
};

/*
* Frame pushed onto the stack before calling the signal handler.
*/
struct signal_frame {
int signo;
siginfo_t *p_siginfo;
ucontext_t *p_ucontext;
/* Above are the arguments passed to the signal handler. */
siginfo_t siginfo;
ucontext_t ucontext;
};

/** Free an existing signal set structure. */
void signal_set_free(struct signal_set *set);

/** Clone an existing signal set. */
struct signal_set *signal_set_clone(struct signal_set *set);

/** Reset all signal actions to their default value. */
void signal_set_reset(struct signal_set *set);

struct signal_context *signal_queue_pop(struct signal_queue *queue,
sigset_t blocked);

/** Remove and free all signals present inside a signal queue. */
size_t signal_queue_flush(struct signal_queue *queue);

void signal_deliver(struct thread *thread, struct signal_context *sig_ctx);

/*
* Generate a process-wide signal.
*/
error_t signal_process(struct process *process, const siginfo_t *sig_info);

/*
* Generate a thread-specific signal.
*/
error_t signal_thread(struct thread *thread, const siginfo_t *sig_info);

/*
* Arch-specific signal related functions.
*/

error_t arch_signal_deliver_catch(struct thread *, const struct signal_action *,
const struct signal_context *);

#endif /* KERNEL_SIGNAL_H */
1 change: 1 addition & 0 deletions include/kernel/syscalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

#include <stddef.h>
#include <sys/stat.h>
#include <sys/signal.h>

typedef struct syscall_args {
u32 nr;
Expand Down
1 change: 1 addition & 0 deletions kernel/arch/i686/build.mk
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ KERNEL_ARCH_SRCS := \
interrupts.asm \
process.c \
process.S \
signal.c \
syscalls.c \
mmu.c \
setup.c \
Expand Down
Loading
Loading