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

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:     }
        !            73:     
        !            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.