My hobby is Unix-like operating systems.
Recently I began writing my own sel4-based Posix compliant OS. Here's the code for internal signal handling functions which presents a kind of backend to help implement functions such as do_kill or do_sigsuspend.
I would like to know what you think about code quality, and any possible errors I've overlooked.
#include "process_definitions.hxx"
#include <signal.h>
#include <array>
#include "signal_definitions.hxx"
#include <sys/types.h>
#include <unistd.h>
#include <kernel_glue.hxx>
using namespace process_methods;
std::array<int, 256> signal_num ;
std::array<pid_t, 256> receiver ;
sigset_t signals_methods::signal_queue::dump_pending(pid_t pid)
{
sigset_t retval;
for (int init = 256; init-- ;)
{
if (receiver[init] == pid )
{
int index = (signal_num[init] / sizeof(sigset_t));
*(retval.__val) = *(retval.__val) & (1 << signal_num[init]);
}
}
return retval;
}
void signals_methods::signal_queue::aggregate_signal_queue()
{
for (int init = 256 ; init--;)
{
send_signal(receiver[init], signal_num[init]);
receiver[init] = 0 ;
signal_num[init] = 0;
}
}
void signals_methods::signal_queue::put_signal_to_queue(pid_t pid, int signal)
{
for (int init = 256; init--;)
{
if (signal_num[init] == 0 && receiver[init] == 0)
{
signal_num[init] = signal;
receiver[init] = pid;
}
}
};
signal_data_struct *signals_methods::get_signal_info(pid_t pid)
{
return &get_process_info(pid)->signal_data;
}
signal_data_struct *signals_methods::get_signal_info()
{
return &get_process_info()->signal_data;
}
void signals_methods::send_signal(pid_t pid, int signal)
{
if (!(get_signal_info(pid)->signal_flags[signal] & (1 << SA_NOMASK)))
{
if (*(get_signal_info(pid)->blocked_mask.__val) & (1 << signal))
{
signals_methods::signal_queue::put_signal_to_queue(pid, signal); //signal is blocked so wait while it will be unblocked
return;
}
}
get_signal_info(pid)->blocked_mask = get_signal_info(pid)->signal_mask[signal];
if (get_signal_info(pid)->handler[signal] == SIG_DFL )
{
exec_default_signal_handler( pid, signal);
return;
}
if (get_signal_info(pid)->handler[signal] == SIG_IGN)
{
return;
}
if(get_signal_info(pid)->thread_suspend_lock)
{
thread_restore(pid);
}
if (get_signal_info(pid)->signal_flags[signal] & SA_SIGINFO)
{
exec_signal_handler_siginfo(pid, &get_signal_info(pid)->handler[signal], signal, &(get_signal_info(pid)->siginfo[signal]));
}
else
{
exec_signal_handler(pid, signal, &get_signal_info(pid)->handler[signal]);
}
}
void signals_methods::exec_default_signal_handler(pid_t pid, int signal)
{
#define dump 0
#define revoke 1
#define stop 2
#define cont 3
#define ign 4
int sigmode [] = {
[SIGABRT] = dump,
[SIGBUS] = dump,
[SIGFPE] = dump,
[SIGILL] = dump,
[SIGQUIT] = dump,
[SIGSEGV] = dump ,
[SIGSYS] = dump ,
[SIGTRAP] = dump ,
[SIGXCPU] = dump ,
[SIGXFSZ] = dump ,
[SIGALRM] = revoke,
[SIGHUP] = revoke,
[SIGINT] = revoke,
[SIGKILL] = revoke,
[SIGPIPE] = revoke,
[SIGTERM] = revoke,
[SIGUSR1] = revoke,
[SIGUSR2] = revoke,
[SIGPOLL] = revoke,
[SIGPROF] = revoke,
[SIGVTALRM] = revoke,
[SIGSTOP] = stop,
[SIGTSTP] = stop ,
[SIGTTIN] = stop,
[SIGTTOU] = stop,
[SIGCONT ] = cont,
[SIGURG] = ign
};
if (!(get_signal_info(pid)->signal_flags[signal] & SA_NOCLDSTOP))
{
signals_methods::signal_queue::put_signal_to_queue(SIGCHLD, get_process_info(pid)->parent_pid);
//get_signal_info(get_process_info(pid)->parent_pid)->siginfo[SIGCHLD]._sifields)
}
switch (sigmode[signal])
{
case dump:
thread_dump(pid);
break;
case revoke:
thread_revoke(pid);
break;
case stop:
thread_stop(pid);
break;
case cont:
thread_restore(pid);
default:
return;
break;
}
};