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

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;
        !            31:     void *pv;
        !            32: } uae_pt;
        !            33: 
        !            34: /* These currently require the maximum size to be known at initialization
        !            35:  * time, but it wouldn't be hard to use a "normal" pipe as an extension once the
        !            36:  * user-level one gets full.
        !            37:  * We queue up to chunks pieces of data before signalling the other thread to
        !            38:  * avoid overhead. */
        !            39: 
        !            40: typedef struct {
        !            41:     uae_sem_t lock;
        !            42:     uae_sem_t reader_wait;
        !            43:     uae_sem_t writer_wait;
        !            44:     uae_pt *data;
        !            45:     int size, chunks;
        !            46:     volatile int rdp, wrp;
        !            47:     volatile int writer_waiting;
        !            48:     volatile int reader_waiting;
        !            49: } smp_comm_pipe;
        !            50: 
        !            51: static __inline__ void init_comm_pipe (smp_comm_pipe *p, int size, int chunks)
        !            52: {
        !            53:     p->data = (uae_pt *)malloc (size*sizeof (uae_pt));
        !            54:     p->size = size;
        !            55:     p->chunks = chunks;
        !            56:     p->rdp = p->wrp = 0;
        !            57:     p->reader_waiting = 0;
        !            58:     p->writer_waiting = 0;
        !            59:     sem_init (&p->lock, 0, 1);
        !            60:     sem_init (&p->reader_wait, 0, 0);
        !            61:     sem_init (&p->writer_wait, 0, 0);
        !            62: }
        !            63: 
        !            64: static __inline__ void maybe_wake_reader (smp_comm_pipe *p, int no_buffer)
        !            65: {
        !            66:     if (p->reader_waiting
        !            67:        && (no_buffer || ((p->wrp - p->rdp + p->size) % p->size) >= p->chunks))
        !            68:     {
        !            69:        p->reader_waiting = 0;
        !            70:        sem_post (&p->reader_wait);
        !            71:     }
        !            72: }
        !            73: 
        !            74: static __inline__ void write_comm_pipe_pt (smp_comm_pipe *p, uae_pt data, int no_buffer)
        !            75: {
        !            76:     int nxwrp = (p->wrp + 1) % p->size;
        !            77: 
        !            78:     if (p->reader_waiting) {
        !            79:        /* No need to do all the locking */
        !            80:        p->data[p->wrp] = data;
        !            81:        p->wrp = nxwrp;
        !            82:        maybe_wake_reader (p, no_buffer);
        !            83:        return;
        !            84:     }
        !            85:     
        !            86:     sem_wait (&p->lock);
        !            87:     if (nxwrp == p->rdp) {
        !            88:        /* Pipe full! */
        !            89:        p->writer_waiting = 1;
        !            90:        sem_post (&p->lock);
        !            91:        /* Note that the reader could get in between here and do a
        !            92:         * sem_post on writer_wait before we wait on it. That's harmless.
        !            93:         * There's a similar case in read_comm_pipe_int_blocking. */
        !            94:        sem_wait (&p->writer_wait);
        !            95:        sem_wait (&p->lock);
        !            96:     }
        !            97:     p->data[p->wrp] = data;
        !            98:     p->wrp = nxwrp;
        !            99:     maybe_wake_reader (p, no_buffer);
        !           100:     sem_post (&p->lock);
        !           101: }
        !           102: 
        !           103: static __inline__ uae_pt read_comm_pipe_pt_blocking (smp_comm_pipe *p)
        !           104: {
        !           105:     uae_pt data;
        !           106: 
        !           107:     sem_wait (&p->lock);
        !           108:     if (p->rdp == p->wrp) {
        !           109:        p->reader_waiting = 1;
        !           110:        sem_post (&p->lock);
        !           111:        sem_wait (&p->reader_wait);
        !           112:        sem_wait (&p->lock);
        !           113:     }
        !           114:     data = p->data[p->rdp];
        !           115:     p->rdp = (p->rdp + 1) % p->size;
        !           116: 
        !           117:     /* We ignore chunks here. If this is a problem, make the size bigger in the init call. */
        !           118:     if (p->writer_waiting) {
        !           119:        p->writer_waiting = 0;
        !           120:        sem_post (&p->writer_wait);
        !           121:     }
        !           122:     sem_post (&p->lock);
        !           123:     return data;
        !           124: }
        !           125: 
        !           126: static __inline__ int comm_pipe_has_data (smp_comm_pipe *p)
        !           127: {
        !           128:     return p->rdp != p->wrp;
        !           129: }
        !           130: 
        !           131: static __inline__ int read_comm_pipe_int_blocking (smp_comm_pipe *p)
        !           132: {
        !           133:     uae_pt foo = read_comm_pipe_pt_blocking (p);
        !           134:     return foo.i;
        !           135: }
        !           136: 
        !           137: static __inline__ void *read_comm_pipe_pvoid_blocking (smp_comm_pipe *p)
        !           138: {
        !           139:     uae_pt foo = read_comm_pipe_pt_blocking (p);
        !           140:     return foo.pv;
        !           141: }
        !           142: 
        !           143: static __inline__ void write_comm_pipe_int (smp_comm_pipe *p, int data, int no_buffer)
        !           144: {
        !           145:     uae_pt foo;
        !           146:     foo.i = 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: }
        !           156: 
        !           157: typedef pthread_t penguin_id;
        !           158: #define BAD_PENGUIN -1
        !           159: 
        !           160: static __inline__ int start_penguin (void *(*f) (void *), void *arg, penguin_id *foo)
        !           161: {
        !           162:     return pthread_create (foo, 0, f, arg);
        !           163: }
        !           164: #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.