summaryrefslogtreecommitdiff
path: root/kernel/src/utils/signal.hpp
blob: ddad3f78a805f4d92ead1c5350bdbe65b82844ee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#pragma once
#include <cstdint>
#include <utils/bitmap.hpp>
#include <generic/lock/spinlock.hpp>

#define SIGHUP    1
#define SIGQUIT   3
#define SIGTRAP   5
#define SIGIOT    SIGABRT
#define SIGBUS    7
#define SIGKILL   9
#define SIGUSR1   10
#define SIGUSR2   12
#define SIGPIPE   13
#define SIGALRM   14
#define SIGSTKFLT 16
#define SIGCHLD   17
#define SIGCONT   18
#define SIGSTOP   19
#define SIGABRT 6
#define SIGTSTP   20
#define SIGTTIN   21
#define SIGTTOU   22
#define SIGURG    23
#define SIGXCPU   24
#define SIGXFSZ   25
#define SIGVTALRM 26
#define SIGPROF         27
#define SIGWINCH  28
#define SIGPOLL   29
#define SIGSYS    31
#define SIGUNUSED SIGSYS
#define SIGCANCEL 32
#define SIGTIMER  33

typedef struct
{
  unsigned long long __val;
} __sigset_t;

typedef __sigset_t sigset_t;

void signal_ret_sigmask(sigset_t* sigmask);

#define __sigmask(sig) \
  (1UL << (((sig) - 1) % 64))

static inline int
__sigword (int sig)
{
  return (sig - 1) / 64;
}

static inline int
__sigismember (sigset_t *set, int sig)
{
  return (set->__val & (1 << (sig - 1))) ? 1 : 0;
}

struct sig_stack {
    void  *ss_sp;     /* Base address of stack */
    int    ss_flags;  /* Flags */
    std::size_t ss_size;   /* Number of bytes in stack */
};

class signal_manager {
private:
    locks::spinlock lock;
    utils::bitmap* bitmap;
    std::uint8_t* sigs;
public:
    signal_manager() {
        bitmap = new utils::bitmap(256);
        sigs = new std::uint8_t[256];
    }

    std::int8_t pop(sigset_t* sigset) {
        this->lock.lock();
        for(int i = 0;i < 256; i++) {
            if(this->bitmap->test(i) && (this->sigs[i] == 9 || !__sigismember(sigset,this->sigs[i]))) {
                std::uint8_t saved_sig = this->sigs[i];
                this->bitmap->clear(i);
                this->lock.unlock();
                return (std::int8_t)saved_sig;
            }
        }
        this->lock.unlock();
        return -1;
    }

    void push(std::uint8_t sig) {
        this->lock.lock();
        for(int i = 0;i < 256; i++) {
            if(!this->bitmap->test(i)) {
                this->bitmap->set(i);
                this->sigs[i] = sig;
                this->lock.unlock();
                return;
            }
        }
        this->lock.unlock(); 
    }

    bool is_not_empty_sigset(sigset_t* sigsetz) {
        this->lock.lock();

        // ban sigset signals :p
        for(int i = 0; i < 128; i++) {
            if(this->bitmap->test(i) && !__sigismember(sigsetz,this->sigs[i])) {
                this->lock.unlock(); // great there's unbanned pending signal
                return 1;
            }
        }

        this->lock.unlock();
        return 0;
    }

};