Annotation of uae/src/include/commpipe.h, revision 1.1.1.2

1.1       root        1:  /*
                      2:   * UAE - The Un*x Amiga Emulator
                      3:   *
                      4:   * Communication between threads
                      5:   *
                      6:   * Copyright 1997, 2001 Bernd Schmidt
                      7:   */
                      8: 
                      9: typedef union {
                     10:     int i;
                     11:     uae_u32 u32;
                     12:     void *pv;
                     13: } uae_pt;
                     14: 
                     15: /* These currently require the maximum size to be known at initialization
                     16:  * time, but it wouldn't be hard to use a "normal" pipe as an extension once the
                     17:  * user-level one gets full.
                     18:  * We queue up to chunks pieces of data before signalling the other thread to
                     19:  * avoid overhead. */
                     20: 
                     21: typedef struct {
                     22:     uae_sem_t lock;
                     23:     uae_sem_t reader_wait;
                     24:     uae_sem_t writer_wait;
                     25:     uae_pt *data;
                     26:     int size, chunks;
                     27:     volatile int rdp, wrp;
                     28:     volatile int writer_waiting;
                     29:     volatile int reader_waiting;
                     30: } smp_comm_pipe;
                     31: 
                     32: static __inline__ void init_comm_pipe (smp_comm_pipe *p, int size, int chunks)
                     33: {
                     34:     p->data = (uae_pt *)malloc (size*sizeof (uae_pt));
                     35:     p->size = size;
                     36:     p->chunks = chunks;
                     37:     p->rdp = p->wrp = 0;
                     38:     p->reader_waiting = 0;
                     39:     p->writer_waiting = 0;
                     40:     uae_sem_init (&p->lock, 0, 1);
                     41:     uae_sem_init (&p->reader_wait, 0, 0);
                     42:     uae_sem_init (&p->writer_wait, 0, 0);
                     43: }
                     44: 
                     45: static __inline__ void destroy_comm_pipe (smp_comm_pipe *p)
                     46: {
                     47:     uae_sem_destroy (&p->lock);
                     48:     uae_sem_destroy (&p->reader_wait);
                     49:     uae_sem_destroy (&p->writer_wait);
                     50: }
                     51: 
                     52: static __inline__ void maybe_wake_reader (smp_comm_pipe *p, int no_buffer)
                     53: {
                     54:     if (p->reader_waiting
                     55:        && (no_buffer || ((p->wrp - p->rdp + p->size) % p->size) >= p->chunks))
                     56:     {
                     57:        p->reader_waiting = 0;
                     58:        uae_sem_post (&p->reader_wait);
                     59:     }
                     60: }
                     61: 
                     62: static __inline__ void write_comm_pipe_pt (smp_comm_pipe *p, uae_pt data, int no_buffer)
                     63: {
                     64:     int nxwrp = (p->wrp + 1) % p->size;
                     65: 
                     66:     if (p->reader_waiting) {
                     67:        /* No need to do all the locking */
                     68:        p->data[p->wrp] = data;
                     69:        p->wrp = nxwrp;
                     70:        maybe_wake_reader (p, no_buffer);
                     71:        return;
                     72:     }
1.1.1.2 ! root       73: 
1.1       root       74:     uae_sem_wait (&p->lock);
                     75:     if (nxwrp == p->rdp) {
                     76:        /* Pipe full! */
                     77:        p->writer_waiting = 1;
                     78:        uae_sem_post (&p->lock);
                     79:        /* Note that the reader could get in between here and do a
                     80:         * sem_post on writer_wait before we wait on it. That's harmless.
                     81:         * There's a similar case in read_comm_pipe_int_blocking. */
                     82:        uae_sem_wait (&p->writer_wait);
                     83:        uae_sem_wait (&p->lock);
                     84:     }
                     85:     p->data[p->wrp] = data;
                     86:     p->wrp = nxwrp;
                     87:     maybe_wake_reader (p, no_buffer);
                     88:     uae_sem_post (&p->lock);
                     89: }
                     90: 
                     91: static __inline__ uae_pt read_comm_pipe_pt_blocking (smp_comm_pipe *p)
                     92: {
                     93:     uae_pt data;
                     94: 
                     95:     uae_sem_wait (&p->lock);
                     96:     if (p->rdp == p->wrp) {
                     97:        p->reader_waiting = 1;
                     98:        uae_sem_post (&p->lock);
                     99:        uae_sem_wait (&p->reader_wait);
                    100:        uae_sem_wait (&p->lock);
                    101:     }
                    102:     data = p->data[p->rdp];
                    103:     p->rdp = (p->rdp + 1) % p->size;
                    104: 
                    105:     /* We ignore chunks here. If this is a problem, make the size bigger in the init call. */
                    106:     if (p->writer_waiting) {
                    107:        p->writer_waiting = 0;
                    108:        uae_sem_post (&p->writer_wait);
                    109:     }
                    110:     uae_sem_post (&p->lock);
                    111:     return data;
                    112: }
                    113: 
                    114: static __inline__ int comm_pipe_has_data (smp_comm_pipe *p)
                    115: {
                    116:     return p->rdp != p->wrp;
                    117: }
                    118: 
                    119: static __inline__ int read_comm_pipe_int_blocking (smp_comm_pipe *p)
                    120: {
                    121:     uae_pt foo = read_comm_pipe_pt_blocking (p);
                    122:     return foo.i;
                    123: }
                    124: static __inline__ uae_u32 read_comm_pipe_u32_blocking (smp_comm_pipe *p)
                    125: {
                    126:     uae_pt foo = read_comm_pipe_pt_blocking (p);
                    127:     return foo.u32;
                    128: }
                    129: 
                    130: static __inline__ void *read_comm_pipe_pvoid_blocking (smp_comm_pipe *p)
                    131: {
                    132:     uae_pt foo = read_comm_pipe_pt_blocking (p);
                    133:     return foo.pv;
                    134: }
                    135: 
                    136: static __inline__ void write_comm_pipe_int (smp_comm_pipe *p, int data, int no_buffer)
                    137: {
                    138:     uae_pt foo;
                    139:     foo.i = data;
                    140:     write_comm_pipe_pt (p, foo, no_buffer);
                    141: }
                    142: 
                    143: static __inline__ void write_comm_pipe_u32 (smp_comm_pipe *p, int data, int no_buffer)
                    144: {
                    145:     uae_pt foo;
                    146:     foo.u32 = data;
                    147:     write_comm_pipe_pt (p, foo, no_buffer);
                    148: }
                    149: 
                    150: static __inline__ void write_comm_pipe_pvoid (smp_comm_pipe *p, void *data, int no_buffer)
                    151: {
                    152:     uae_pt foo;
                    153:     foo.pv = data;
                    154:     write_comm_pipe_pt (p, foo, no_buffer);
                    155: }

unix.superglobalmegacorp.com

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