/*
**  pth.h -- Pth public API definitions
**
**  Copyright (c) 1999 Ralf S. Engelschall <rse@engelschall.com>
**
**  This file is part of GNU Pth, a non-preemptive thread scheduling
**  library which can be found at http://www.gnu.org/software/pth/.
**
**  This library is free software; you can redistribute it and/or
**  modify it under the terms of the GNU Library General Public
**  License as published by the Free Software Foundation; either
**  version 2 of the License, or (at your option) any later version.
**
**  This library is distributed in the hope that it will be useful,
**  but WITHOUT ANY WARRANTY; without even the implied warranty of
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
**  Library General Public License for more details.
**
**  You should have received a copy of the GNU Library General Public
**  License along with this library; if not, write to the Free Software
**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
**  USA, or contact Ralf S. Engelschall <rse@engelschall.com>.
*/

#ifndef _PTH_H_
#define _PTH_H_

    /* the library version */
#ifndef PTH_VERSION
#define PTH_VERSION 0x100203
#endif

    /* essential headers */
#include <sys/types.h>     /* for ssize_t, off_t */
#include <sys/time.h>      /* for struct timeval */
#include <sys/socket.h>    /* for sockaddr */
#include <sys/signal.h>    /* for sigset_t */

    /* fallbacks for essential typedefs */
/* typedef int pid_t; */
/* typedef unsigned int size_t; */
/* typedef unsigned int ssize_t; */
/* typedef int off_t; */
/* typedef int sig_atomic_t; */

    /* extra structure definitions */
struct timeval;
    
    /* essential values */
#ifndef FALSE
#define FALSE (0)
#endif
#ifndef TRUE
#define TRUE (!FALSE)
#endif
#ifndef NUL
#define NUL '\0'
#endif
#ifndef NULL
#define NULL (void *)0
#endif

    /* bitmask generation */
#define _BIT(n) (1<<(n))

    /* C++ support */
#ifdef __cplusplus
#define BEGIN_DECLARATION extern "C" {
#define END_DECLARATION   }
#else
#define BEGIN_DECLARATION /*nop*/
#define END_DECLARATION   /*nop*/
#endif

BEGIN_DECLARATION

    /* some global constants */
#define PTH_KEY_MAX                  256
#define PTH_ATFORK_MAX               128
#define PTH_DESTRUCTOR_ITERATIONS    4

    /* system call mapping support type (soft variant can be overridden) */
#define PTH_SYSCALL_HARD 0
#ifndef PTH_SYSCALL_SOFT
#define PTH_SYSCALL_SOFT 1
#endif

    /* queries for pth_ctrl() */
#define PTH_CTRL_GETAVLOAD           _BIT(1)
#define PTH_CTRL_GETPRIO             _BIT(2)
#define PTH_CTRL_GETNAME             _BIT(3)
#define PTH_CTRL_GETTHREADS_NEW      _BIT(4)
#define PTH_CTRL_GETTHREADS_READY    _BIT(5)
#define PTH_CTRL_GETTHREADS_RUNNING  _BIT(6)
#define PTH_CTRL_GETTHREADS_WAITING  _BIT(7)
#define PTH_CTRL_GETTHREADS_DEAD     _BIT(8)
#define PTH_CTRL_GETTHREADS          (PTH_CTRL_GETTHREADS_NEW|\
                                      PTH_CTRL_GETTHREADS_READY|\
                                      PTH_CTRL_GETTHREADS_RUNNING|\
                                      PTH_CTRL_GETTHREADS_WAITING|\
                                      PTH_CTRL_GETTHREADS_DEAD)

    /* the time value structure */
typedef struct timeval pth_time_t;

    /* the unique thread id/handle */
typedef struct pth_st *pth_t;
struct pth_st;

    /* thread states */
typedef enum pth_state_en {
    PTH_STATE_SCHEDULER = 0,         /* the special scheduler thread only */
    PTH_STATE_NEW,                   /* spawned, but still not dispatched */
    PTH_STATE_READY,                 /* ready, waiting to be dispatched */
    PTH_STATE_WAITING,               /* suspended, waiting until event occurred */
    PTH_STATE_DEAD                   /* terminated, waiting to be joined */
} pth_state_t;

    /* thread priority values */
#define PTH_PRIO_MAX                 +5
#define PTH_PRIO_STD                  0
#define PTH_PRIO_MIN                 -5

    /* the thread attribute structure */
typedef struct pth_attr_st *pth_attr_t;
struct pth_attr_st;

    /* attribute set/get commands for pth_attr_{get,set}() */
enum {
    PTH_ATTR_PRIO,           /* RW [int]               priority of thread                 */
    PTH_ATTR_NAME,           /* RW [char *]            name of thread                     */
    PTH_ATTR_JOINABLE,       /* RW [int]               thread detachment type             */
    PTH_ATTR_CANCEL_STATE,   /* RW [unsigned int]      thread cancellation state          */ 
    PTH_ATTR_STACK_SIZE,     /* RW [unsigned int]      stack size                         */
    PTH_ATTR_STACK_ADDR,     /* RW [char *]            stack lower address                */
    PTH_ATTR_TIME_SPAWN,     /* RO [pth_time_t]        time thread was spawned            */
    PTH_ATTR_TIME_LAST,      /* RO [pth_time_t]        time thread was last dispatched    */
    PTH_ATTR_TIME_RAN,       /* RO [pth_time_t]        time thread was running            */
    PTH_ATTR_START_FUNC,     /* RO [void *(*)(void *)] thread start function              */
    PTH_ATTR_START_ARG,      /* RO [void *]            thread start argument              */
    PTH_ATTR_STATE,          /* RO [pth_state_t]       scheduling state                   */
    PTH_ATTR_EVENTS,         /* RO [pth_event_t]       events the thread is waiting for   */
    PTH_ATTR_BOUND           /* RO [int]               whether object is bound to thread  */
};

    /* default thread attribute */
#define PTH_ATTR_DEFAULT (pth_attr_t)(0)

    /* the event structure */
typedef struct pth_event_st *pth_event_t;
struct pth_event_st;

    /* event subject classes */
#define PTH_EVENT_FD                 _BIT(1)
#define PTH_EVENT_SELECT             _BIT(2)
#define PTH_EVENT_SIGS               _BIT(3)
#define PTH_EVENT_TIME               _BIT(4)
#define PTH_EVENT_MSG                _BIT(5)
#define PTH_EVENT_MUTEX              _BIT(6)
#define PTH_EVENT_COND               _BIT(7)
#define PTH_EVENT_TID                _BIT(8)
#define PTH_EVENT_PID                _BIT(9)
#define PTH_EVENT_FUNC               _BIT(10)

    /* event occurange restrictions */
#define PTH_UNTIL_OCCURRED           _BIT(11)
#define PTH_UNTIL_FD_READABLE        _BIT(12)
#define PTH_UNTIL_FD_WRITEABLE       _BIT(13)
#define PTH_UNTIL_FD_EXCEPTION       _BIT(14)
#define PTH_UNTIL_TID_NEW            _BIT(15)
#define PTH_UNTIL_TID_READY          _BIT(16)
#define PTH_UNTIL_TID_WAITING        _BIT(17)
#define PTH_UNTIL_TID_DEAD           _BIT(18)

    /* event structure handling modes */
#define PTH_MODE_REUSE               _BIT(20)
#define PTH_MODE_CHAIN               _BIT(21)
#define PTH_MODE_STATIC              _BIT(22)

    /* event deallocation types */
enum { PTH_FREE_THIS, PTH_FREE_ALL };

    /* event walking directions */
#define PTH_WALK_NEXT                _BIT(1)
#define PTH_WALK_PREV                _BIT(2)

    /* the key type and init value */
typedef int pth_key_t;
#define PTH_KEY_INIT (-1)

    /* the once structure and init value */
typedef int pth_once_t;
#define PTH_ONCE_INIT FALSE

    /* general ring structure */
typedef struct pth_ringnode_st pth_ringnode_t;
struct pth_ringnode_st {
    pth_ringnode_t *rn_next;
    pth_ringnode_t *rn_prev;
};
typedef struct pth_ring_st pth_ring_t;
struct pth_ring_st {
    pth_ringnode_t *rn_hook;
};
#define PTH_RING_INIT { NULL }

    /* cancellation values */
#define PTH_CANCEL_ENABLE            _BIT(0)
#define PTH_CANCEL_DISABLE           _BIT(1)
#define PTH_CANCEL_ASYNCHRONOUS      _BIT(2)
#define PTH_CANCEL_DEFERRED          _BIT(3)
#define PTH_CANCEL_DEFAULT           (PTH_CANCEL_ENABLE|PTH_CANCEL_DEFERRED)
#define PTH_CANCELED                 ((void *)-1)

   /* mutex values */
#define PTH_MUTEX_INITIALIZED        _BIT(0)
#define PTH_MUTEX_LOCKED             _BIT(1)
#define PTH_MUTEX_INIT               { {NULL, NULL}, PTH_MUTEX_INITIALIZED, NULL, 0 }

   /* read-write lock values */
enum { PTH_RWLOCK_RD, PTH_RWLOCK_RW };
#define PTH_RWLOCK_INITIALIZED       _BIT(0)
#define PTH_RWLOCK_INIT              { PTH_RWLOCK_INITIALIZED, PTH_RWLOCK_RD, 0, \
                                       PTH_MUTEX_INIT, PTH_MUTEX_INIT }

   /* condition variable values */
#define PTH_COND_INITIALIZED         _BIT(0)
#define PTH_COND_SIGNALED            _BIT(1)
#define PTH_COND_BROADCAST           _BIT(2)
#define PTH_COND_HANDLED             _BIT(3)
#define PTH_COND_INIT                { PTH_COND_INITIALIZED }

    /* the message port structure */
typedef struct pth_msgport_st *pth_msgport_t;
struct pth_msgport_st;

    /* the message structure */
typedef struct pth_message_st pth_message_t;
struct pth_message_st { /* not hidden to allow inclusion */
    pth_ringnode_t m_node;
    pth_msgport_t  m_replyport;
    unsigned int   m_size;
    void          *m_data;
};

    /* the mutex structure */
typedef struct pth_mutex_st pth_mutex_t;
struct pth_mutex_st { /* not hidden to avoid destructor */
    pth_ringnode_t mx_node;
    int            mx_state;
    pth_t          mx_owner;
    unsigned long  mx_count;
};

    /* the read-write lock structure */
typedef struct pth_rwlock_st pth_rwlock_t;
struct pth_rwlock_st { /* not hidden to avoid destructor */
    int            rw_state;
    unsigned int   rw_mode;
    unsigned long  rw_readers;
    pth_mutex_t    rw_mutex_rd;
    pth_mutex_t    rw_mutex_rw;
};

    /* the condition variable structure */
typedef struct pth_cond_st pth_cond_t;
struct pth_cond_st { /* not hidden to avoid destructor */
    unsigned long cn_state;
};

    /* optionally fake poll(2) data structure and options */
#define PTH_FAKE_POLL 1
#if !(PTH_FAKE_POLL)
/* use vendor poll(2) environment */
#include <poll.h>
#ifndef INFTIM
#define INFTIM (-1)
#endif
#else
/* fake a poll(2) environment */
#define POLLIN      0x0001      /* any readable data available */
#define POLLPRI     0x0002      /* OOB/Urgent readable data */
#define POLLOUT     0x0004      /* file descriptor is writeable */
#define POLLERR     0x0008      /* some poll error occurred */
#define POLLHUP     0x0010      /* file descriptor was "hung up" */
#define POLLNVAL    0x0020      /* requested events "invalid" */
#define POLLRDNORM  POLLIN
#define POLLRDBAND  POLLIN
#define POLLWRNORM  POLLOUT
#define POLLWRBAND  POLLOUT
#ifndef INFTIM
#define INFTIM      (-1)        /* poll infinite */
#endif
struct pollfd {
    int fd;                     /* which file descriptor to poll */
    short events;               /* events we are interested in */
    short revents;              /* events found on return */
};
#endif

    /* optionally fake readv(2)/writev(2) data structure and options */
#define PTH_FAKE_RWV 0
#if !(PTH_FAKE_RWV)
/* use vendor readv(2)/writev(2) environment */
#include <sys/uio.h>
#else
/* fake a readv(2)/writev(2) environment */
struct iovec {
    void  *iov_base;  /* memory base address */
    size_t iov_len;   /* memory chunk length */
};
#endif

    /* global functions */
int            pth_init(void);
void           pth_kill(void);
long           pth_ctrl(unsigned long, ...);
long           pth_version(void);

    /* thread attribute functions */
pth_attr_t     pth_attr_of(pth_t);
pth_attr_t     pth_attr_new(void);
int            pth_attr_init(pth_attr_t);
int            pth_attr_set(pth_attr_t, int, ...);
int            pth_attr_get(pth_attr_t, int, ...);
int            pth_attr_destroy(pth_attr_t);

    /* thread functions */
pth_t          pth_spawn(pth_attr_t, void *(*)(void *), void *);
int            pth_once(pth_once_t *, void (*)(void *), void *);
pth_t          pth_self(void);
void           pth_yield(pth_t);
int            pth_nap(pth_time_t);
int            pth_wait(pth_event_t);
int            pth_cancel(pth_t);
int            pth_abort(pth_t);
int            pth_raise(pth_t, int);
int            pth_join(pth_t, void **);
void           pth_exit(void *);

    /* utility functions */
int            pth_nonblocking(int);
pth_time_t     pth_time(int, int);
pth_time_t     pth_timeout(int, int);

    /* cancellation functions */
void           pth_cancel_state(int, int *);
void           pth_cancel_point(void);

    /* event functions */
pth_event_t    pth_event(unsigned long, ...); 
unsigned long  pth_event_typeof(pth_event_t);
int            pth_event_extract(pth_event_t ev, ...);
pth_event_t    pth_event_concat(pth_event_t, ...);
pth_event_t    pth_event_isolate(pth_event_t);
pth_event_t    pth_event_walk(pth_event_t, unsigned int);
int            pth_event_occurred(pth_event_t);
int            pth_event_free(pth_event_t, int);

    /* key-based storage functions */
int            pth_key_create(pth_key_t *, void (*)(void *));
int            pth_key_delete(pth_key_t);
int            pth_key_setdata(pth_key_t, const void *);
void          *pth_key_getdata(pth_key_t);

    /* message port functions */
pth_msgport_t  pth_msgport_create(const char *);
void           pth_msgport_destroy(pth_msgport_t);
pth_msgport_t  pth_msgport_find(const char *);
int            pth_msgport_pending(pth_msgport_t);
int            pth_msgport_put(pth_msgport_t, pth_message_t *);
pth_message_t *pth_msgport_get(pth_msgport_t);
int            pth_msgport_reply(pth_message_t *);

    /* cleanup handler functions */
int            pth_cleanup_push(void (*)(void *), void *);
int            pth_cleanup_pop(int);

    /* process forking functions */
int            pth_atfork_push(void (*)(void *), void (*)(void *), void (*)(void *), void *);
int            pth_atfork_pop(void);
pid_t          pth_fork(void);

    /* synchronization functions */
int            pth_mutex_init(pth_mutex_t *);
int            pth_mutex_acquire(pth_mutex_t *, int, pth_event_t);
int            pth_mutex_release(pth_mutex_t *);
int            pth_rwlock_init(pth_rwlock_t *);
int            pth_rwlock_acquire(pth_rwlock_t *, int, int, pth_event_t);
int            pth_rwlock_release(pth_rwlock_t *);
int            pth_cond_init(pth_cond_t *);
int            pth_cond_await(pth_cond_t *, pth_mutex_t *, pth_event_t);
int            pth_cond_notify(pth_cond_t *, int);

    /* generalized variants of replacement functions */
int            pth_sigwait_ev(const sigset_t *, int *, pth_event_t);
int            pth_connect_ev(int, const struct sockaddr *, int, pth_event_t);
int            pth_accept_ev(int, struct sockaddr *, int *, pth_event_t);
int            pth_select_ev(int, fd_set *, fd_set *, fd_set *, struct timeval *, pth_event_t);
int            pth_poll_ev(struct pollfd *, unsigned int, int, pth_event_t);
ssize_t        pth_read_ev(int, void *, size_t, pth_event_t);
ssize_t        pth_write_ev(int, const void *, size_t, pth_event_t);
ssize_t        pth_readv_ev(int, const struct iovec *, int, pth_event_t);
ssize_t        pth_writev_ev(int, const struct iovec *, int, pth_event_t);

    /* standard replacement functions */
int            pth_usleep(unsigned int);
unsigned int   pth_sleep(unsigned int);
pid_t          pth_waitpid(pid_t, int *, int);
int            pth_sigmask(int, const sigset_t *, sigset_t *);
int            pth_sigwait(const sigset_t *, int *);
int            pth_connect(int, const struct sockaddr *, int);
int            pth_accept(int, struct sockaddr *, int *);
int            pth_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
int            pth_poll(struct pollfd *, unsigned int, int);
ssize_t        pth_read(int, void *, size_t);
ssize_t        pth_write(int, const void *, size_t);
ssize_t        pth_readv(int, const struct iovec *, int);
ssize_t        pth_writev(int, const struct iovec *, int);
ssize_t        pth_pread(int, void *, size_t, off_t);
ssize_t        pth_pwrite(int, const void *, size_t, off_t);

END_DECLARATION

    /* soft system call mapping support */
#if PTH_SYSCALL_SOFT && !defined(_PTH_PRIVATE)
#define fork       pth_fork
#define sleep      pth_sleep
#define sigwait    pth_sigwait
#define waitpid    pth_waitpid
#define select     pth_select
#define poll       pth_poll
#define connect    pth_connect
#define accept     pth_accept
#define read       pth_read
#define write      pth_write
#define readv      pth_readv
#define writev     pth_writev
#define pread      pth_pread
#define pwrite     pth_pwrite
#endif

#endif /* _PTH_H_ */

