Annotation of uae/src/td-posix/penguin.h, revision 1.1.1.2

1.1       root        1:  /*
                      2:   * UAE - The Un*x Amiga Emulator
                      3:   * 
                      4:   * "SSSSSYYYMMMETTTTTRIICCC MMMMMMULTIIIIIII PPPPPPENGGGGUIIIIN!!!!!"
                      5:   *   -- David S. Miller
                      6:   * 
                      7:   * Symmetric Multi Penguin support - of course this also works on single
                      8:   * penguin machines, but it's kind of pointless there.
                      9:   * 
                     10:   * This is a rough, simpleminded draft - expect changes when it gets ported 
                     11:   * to other systems, and/or rewritten by someone who has experience with this
                     12:   * kind of thing. This is just to get started and to see how this works out.
                     13:   *
                     14:   * Copyright 1997 Bernd Schmidt
                     15:   */
                     16: 
                     17: #include <pthread.h>
                     18: #include <semaphore.h>
                     19: 
                     20: /* Sempahores. We use POSIX semaphores; if you are porting this to a machine
                     21:  * with different ones, make them look like POSIX semaphores. */
                     22: typedef sem_t uae_sem_t;
                     23: #define uae_sem_init sem_init
                     24: #define uae_sem_post sem_post
                     25: #define uae_sem_wait sem_wait
                     26: #define uae_sem_trywait sem_trywait
                     27: #define uae_sem_getvalue sem_getvalue
                     28: 
                     29: typedef union {
                     30:     int i;
1.1.1.2 ! root       31:     uae_u32 u32;
1.1       root       32:     void *pv;
                     33: } uae_pt;
                     34: 
                     35: /* These currently require the maximum size to be known at initialization
                     36:  * time, but it wouldn't be hard to use a "normal" pipe as an extension once the
                     37:  * user-level one gets full.
                     38:  * We queue up to chunks pieces of data before signalling the other thread to
                     39:  * avoid overhead. */
                     40: 
                     41: typedef struct {
                     42:     uae_sem_t lock;
                     43:     uae_sem_t reader_wait;
                     44:     uae_sem_t writer_wait;
                     45:     uae_pt *data;
                     46:     int size, chunks;
                     47:     volatile int rdp, wrp;
                     48:     volatile int writer_waiting;
                     49:     volatile int reader_waiting;
                     50: } smp_comm_pipe;
                     51: 
                     52: static __inline__ void init_comm_pipe (smp_comm_pipe *p, int size, int chunks)
                     53: {
                     54:     p->data = (uae_pt *)malloc (size*sizeof (uae_pt));
                     55:     p->size = size;
                     56:     p->chunks = chunks;
                     57:     p->rdp = p->wrp = 0;
                     58:     p->reader_waiting = 0;
                     59:     p->writer_waiting = 0;
                     60:     sem_init (&p->lock, 0, 1);
                     61:     sem_init (&p->reader_wait, 0, 0);
                     62:     sem_init (&p->writer_wait, 0, 0);
                     63: }
                     64: 
                     65: static __inline__ void maybe_wake_reader (smp_comm_pipe *p, int no_buffer)
                     66: {
                     67:     if (p->reader_waiting
                     68:        && (no_buffer || ((p->wrp - p->rdp + p->size) % p->size) >= p->chunks))
                     69:     {
                     70:        p->reader_waiting = 0;
                     71:        sem_post (&p->reader_wait);
                     72:     }
                     73: }
                     74: 
                     75: static __inline__ void write_comm_pipe_pt (smp_comm_pipe *p, uae_pt data, int no_buffer)
                     76: {
                     77:     int nxwrp = (p->wrp + 1) % p->size;
                     78: 
                     79:     if (p->reader_waiting) {
                     80:        /* No need to do all the locking */
                     81:        p->data[p->wrp] = data;
                     82:        p->wrp = nxwrp;
                     83:        maybe_wake_reader (p, no_buffer);
                     84:        return;
                     85:     }
                     86:     
                     87:     sem_wait (&p->lock);
                     88:     if (nxwrp == p->rdp) {
                     89:        /* Pipe full! */
                     90:        p->writer_waiting = 1;
                     91:        sem_post (&p->lock);
                     92:        /* Note that the reader could get in between here and do a
                     93:         * sem_post on writer_wait before we wait on it. That's harmless.
                     94:         * There's a similar case in read_comm_pipe_int_blocking. */
                     95:        sem_wait (&p->writer_wait);
                     96:        sem_wait (&p->lock);
                     97:     }
                     98:     p->data[p->wrp] = data;
                     99:     p->wrp = nxwrp;
                    100:     maybe_wake_reader (p, no_buffer);
                    101:     sem_post (&p->lock);
                    102: }
                    103: 
                    104: static __inline__ uae_pt read_comm_pipe_pt_blocking (smp_comm_pipe *p)
                    105: {
                    106:     uae_pt data;
                    107: 
                    108:     sem_wait (&p->lock);
                    109:     if (p->rdp == p->wrp) {
                    110:        p->reader_waiting = 1;
                    111:        sem_post (&p->lock);
                    112:        sem_wait (&p->reader_wait);
                    113:        sem_wait (&p->lock);
                    114:     }
                    115:     data = p->data[p->rdp];
                    116:     p->rdp = (p->rdp + 1) % p->size;
                    117: 
                    118:     /* We ignore chunks here. If this is a problem, make the size bigger in the init call. */
                    119:     if (p->writer_waiting) {
                    120:        p->writer_waiting = 0;
                    121:        sem_post (&p->writer_wait);
                    122:     }
                    123:     sem_post (&p->lock);
                    124:     return data;
                    125: }
                    126: 
                    127: static __inline__ int comm_pipe_has_data (smp_comm_pipe *p)
                    128: {
                    129:     return p->rdp != p->wrp;
                    130: }
                    131: 
                    132: static __inline__ int read_comm_pipe_int_blocking (smp_comm_pipe *p)
                    133: {
                    134:     uae_pt foo = read_comm_pipe_pt_blocking (p);
                    135:     return foo.i;
                    136: }
1.1.1.2 ! root      137: static __inline__ uae_u32 read_comm_pipe_u32_blocking (smp_comm_pipe *p)
        !           138: {
        !           139:     uae_pt foo = read_comm_pipe_pt_blocking (p);
        !           140:     return foo.u32;
        !           141: }
1.1       root      142: 
                    143: static __inline__ void *read_comm_pipe_pvoid_blocking (smp_comm_pipe *p)
                    144: {
                    145:     uae_pt foo = read_comm_pipe_pt_blocking (p);
                    146:     return foo.pv;
                    147: }
                    148: 
                    149: static __inline__ void write_comm_pipe_int (smp_comm_pipe *p, int data, int no_buffer)
                    150: {
                    151:     uae_pt foo;
                    152:     foo.i = data;
                    153:     write_comm_pipe_pt (p, foo, no_buffer);
                    154: }
                    155: 
1.1.1.2 ! root      156: static __inline__ void write_comm_pipe_u32 (smp_comm_pipe *p, int data, int no_buffer)
        !           157: {
        !           158:     uae_pt foo;
        !           159:     foo.u32 = data;
        !           160:     write_comm_pipe_pt (p, foo, no_buffer);
        !           161: }
        !           162: 
1.1       root      163: static __inline__ void write_comm_pipe_pvoid (smp_comm_pipe *p, void *data, int no_buffer)
                    164: {
                    165:     uae_pt foo;
                    166:     foo.pv = data;
                    167:     write_comm_pipe_pt (p, foo, no_buffer);
                    168: }
                    169: 
                    170: typedef pthread_t penguin_id;
                    171: #define BAD_PENGUIN -1
                    172: 
                    173: static __inline__ int start_penguin (void *(*f) (void *), void *arg, penguin_id *foo)
                    174: {
                    175:     return pthread_create (foo, 0, f, arg);
                    176: }
                    177: #define UAE_PENGUIN_EXIT pthread_exit(0)

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.