/*
 * Copyright (c) 2006-2022, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2017-09-12     Bernard      The first version
 * 2021-07-21     Meco Man     move to libc/common
 */

#ifndef __SYS_SIGNAL_H__
#define __SYS_SIGNAL_H__

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

#ifdef RT_USING_MUSLLIBC
/* this is required for musl <signal.h> */
#ifndef _POSIX_SOURCE
#define _POSIX_SOURCE
#include <signal.h>
/* limiting influence of _POSIX_SOURCE */
#undef _POSIX_SOURCE

#else /* ndef _POSIX_SOURCE */
#include <signal.h>
#endif

#else

#include <stdint.h>
#include <sys/types.h>

/* sigev_notify values
   NOTE: P1003.1c/D10, p. 34 adds SIGEV_THREAD.  */

#define SIGEV_NONE   1  /* No asynchronous notification shall be delivered */
                        /*   when the event of interest occurs. */
#define SIGEV_SIGNAL 0  /* A queued signal, with an application defined */
                        /*  value, shall be delivered when the event of */
                        /*  interest occurs. */
#define SIGEV_THREAD 2  /* A notification function shall be called to */
                        /*   perform notification. */

/*  Signal Generation and Delivery, P1003.1b-1993, p. 63
    NOTE: P1003.1c/D10, p. 34 adds sigev_notify_function and
          sigev_notify_attributes to the sigevent structure.  */
union sigval
{
    int    sival_int;    /* Integer signal value */
    void  *sival_ptr;    /* Pointer signal value */
};

struct sigevent
{
    union sigval sigev_value;
    int          sigev_signo;                /* Signal number */
    int          sigev_notify;               /* Notification type */
    void         (*sigev_notify_function)( union sigval );
                                             /* Notification function */
    void         *sigev_notify_attributes;   /* Notification Attributes, really pthread_attr_t */
};

struct siginfo
{
    uint16_t si_signo;
    uint16_t si_code;
    union sigval si_value;
};
typedef struct siginfo siginfo_t;

#define SI_USER     0x01    /* Signal sent by kill(). */
#define SI_QUEUE    0x02    /* Signal sent by sigqueue(). */
#define SI_TIMER    0x03    /* Signal generated by expiration of a timer set by timer_settime(). */
#define SI_ASYNCIO  0x04    /* Signal generated by completion of an asynchronous I/O request. */
#define SI_MESGQ    0x05    /* Signal generated by arrival of a message on an empty message queue. */

typedef void (*_sig_func_ptr)(int);
typedef unsigned long sigset_t;

struct sigaction
{
    _sig_func_ptr sa_handler;
    sigset_t sa_mask;
    int sa_flags;
};

/*
 * Structure used in sigaltstack call.
 */
typedef struct sigaltstack
{
  void     *ss_sp;    /* Stack base or pointer.  */
  int       ss_flags; /* Flags.  */
  size_t    ss_size;  /* Stack size.  */
} stack_t;

#define SIG_SETMASK 0   /* set mask with sigprocmask() */
#define SIG_BLOCK   1   /* set of signals to block */
#define SIG_UNBLOCK 2   /* set of signals to, well, unblock */

#define sigaddset(what,sig) (*(what) |= (1<<(sig)), 0)
#define sigdelset(what,sig) (*(what) &= ~(1<<(sig)), 0)
#define sigemptyset(what)   (*(what) = 0, 0)
#define sigfillset(what)    (*(what) = ~(0), 0)
#define sigismember(what,sig) (((*(what)) & (1<<(sig))) != 0)

int sigprocmask (int how, const sigset_t *set, sigset_t *oset);
int sigpending (sigset_t *set);
int sigsuspend (const sigset_t *set);

#include "time.h"
int sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec *timeout);
int sigwait(const sigset_t *set, int *sig);
int sigwaitinfo(const sigset_t *set, siginfo_t *info);
int raise(int sig);
int sigqueue(pid_t pid, int signo, const union sigval value);
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

#ifdef __ARMCC_VERSION
#define SIGHUP       1
/* #define SIGINT       2 */
#define SIGQUIT      3
/* #define SIGILL       4 */
#define SIGTRAP      5
/* #define SIGABRT      6 */
#define SIGEMT       7
/* #define SIGFPE       8 */
#define SIGKILL      9
#define SIGBUS      10
/* #define SIGSEGV     11 */
#define SIGSYS      12
#define SIGPIPE     13
#define SIGALRM     14
/* #define SIGTERM     15 */
#define SIGURG      16
#define SIGSTOP     17
#define SIGTSTP     18
#define SIGCONT     19
#define SIGCHLD     20
#define SIGTTIN     21
#define SIGTTOU     22
#define SIGPOLL     23
#define SIGWINCH    24
#define SIGXCPU     24  /* exceeded CPU time limit */
#define SIGXFSZ     25  /* exceeded file size limit */
#define SIGVTALRM   26  /* virtual time alarm */
/* #define SIGUSR1     25 */
/* #define SIGUSR2     26 */
#define SIGRTMIN    27
#define SIGRTMAX    31
#define NSIG        32

#elif defined(__IAR_SYSTEMS_ICC__)
#define SIGHUP       1
#define SIGINT       2
#define SIGQUIT      3
#define SIGILL       4
#define SIGTRAP      5
/* #define SIGABRT      6 */
#define SIGEMT       7
#define SIGFPE       8
#define SIGKILL      9
#define SIGBUS      10
#define SIGSEGV     11
#define SIGSYS      12
#define SIGPIPE     13
#define SIGALRM     14
#define SIGTERM     15
#define SIGURG      16
#define SIGSTOP     17
#define SIGTSTP     18
#define SIGCONT     19
#define SIGCHLD     20
#define SIGTTIN     21
#define SIGTTOU     22
#define SIGPOLL     23
#define SIGWINCH    24
#define SIGXCPU     24  /* exceeded CPU time limit */
#define SIGXFSZ     25  /* exceeded file size limit */
#define SIGVTALRM   26  /* virtual time alarm */
#define SIGUSR1     25
#define SIGUSR2     26
#define SIGRTMIN    27
#define SIGRTMAX    31
#define NSIG        32

#elif defined(__GNUC__)
#define SIGHUP  1   /* hangup */
#define SIGINT  2   /* interrupt */
#define SIGQUIT 3   /* quit */
#define SIGILL  4   /* illegal instruction (not reset when caught) */
#define SIGTRAP 5   /* trace trap (not reset when caught) */
#define SIGIOT  6   /* IOT instruction */
#define SIGABRT 6   /* used by abort, replace SIGIOT in the future */
#define SIGEMT  7   /* EMT instruction */
#define SIGFPE  8   /* floating point exception */
#define SIGKILL 9   /* kill (cannot be caught or ignored) */
#define SIGBUS  10  /* bus error */
#define SIGSEGV 11  /* segmentation violation */
#define SIGSYS  12  /* bad argument to system call */
#define SIGPIPE 13  /* write on a pipe with no one to read it */
#define SIGALRM 14  /* alarm clock */
#define SIGTERM 15  /* software termination signal from kill */
#define SIGURG  16  /* urgent condition on IO channel */
#define SIGSTOP 17  /* sendable stop signal not from tty */
#define SIGTSTP 18  /* stop signal from tty */
#define SIGCONT 19  /* continue a stopped process */
#define SIGCHLD 20  /* to parent on child stop or exit */
#define SIGCLD  20  /* System V name for SIGCHLD */
#define SIGTTIN 21  /* to readers pgrp upon background tty read */
#define SIGTTOU 22  /* like TTIN for output if (tp->t_local&LTOSTOP) */
#define SIGIO   23  /* input/output possible signal */
#define SIGPOLL SIGIO   /* System V name for SIGIO */
#define SIGXCPU 24  /* exceeded CPU time limit */
#define SIGXFSZ 25  /* exceeded file size limit */
#define SIGVTALRM 26    /* virtual time alarm */
#define SIGPROF 27  /* profiling time alarm */
#define SIGWINCH 28 /* window changed */
#define SIGLOST 29  /* resource lost (eg, record-lock lost) */
#define SIGUSR1 30  /* user defined signal 1 */
#define SIGUSR2 31  /* user defined signal 2 */
#define NSIG    32      /* signal 0 implied */
#endif /* __ARMCC_VERSION */

/* Some applications take advantage of the fact that <sys/signal.h>
 * and <signal.h> are equivalent in glibc.  Allow for that here.  */
#include <signal.h>

#ifndef SIG_ERR
#define SIG_ERR  ((void (*)(int))-1)
#endif

#ifndef SIG_DFL
#define SIG_DFL  ((void (*)(int)) 0)
#endif

#ifndef SIG_IGN
#define SIG_IGN  ((void (*)(int)) 1)
#endif

#endif /* RT_USING_MUSLLIBC */

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* __SYS_SIGNAL_H__ */

