static enum ach_status wrlock(ach_channel_t * chan) { enum ach_status r = chan_lock(chan) ; if( ACH_OK != r ) return r; chan->shm->sync.dirty = 1; return ACH_OK; }
static enum ach_status rdlock( ach_channel_t *chan, int wait, const struct timespec *abstime ) { ach_header_t *shm = chan->shm; { enum ach_status r = chan_lock(chan); if( ACH_OK != r ) return r; } enum ach_status r = ACH_BUG; while(ACH_BUG == r) { if( chan->cancel ) { /* check operation cancelled */ pthread_mutex_unlock( &shm->sync.mutex ); r = ACH_CANCELED; } else if( !wait ) r = ACH_OK; /* check no wait */ else if ( chan->seq_num != shm->last_seq ) r = ACH_OK; /* check if got a frame */ /* else condition wait */ else { int i = abstime ? pthread_cond_timedwait( &shm->sync.cond, &shm->sync.mutex, abstime ) : pthread_cond_wait( &shm->sync.cond, &shm->sync.mutex ); enum ach_status c = check_lock(i, chan, 1); if( ACH_OK != c ) r = c; /* check r and condition next iteration */ } } return r; }
static enum ach_status rdlock_wait(ach_channel_t * chan, const struct timespec *reltime) { int res; struct ach_header *shm = chan->shm; volatile uint64_t *c_seq = &chan->seq_num, *s_seq = &shm->last_seq; volatile unsigned int *cancel = &chan->cancel; enum ach_status r; for(;;) { /* do the wait */ if (reltime->tv_sec != 0 || reltime->tv_nsec != 0) { res = wait_event_interruptible_timeout( shm->sync. readq, ((*c_seq != *s_seq) || *cancel), timespec_to_jiffies (reltime) ); if (0 == res) return ACH_TIMEOUT; } else { res = wait_event_interruptible( shm->sync.readq, ((*c_seq != *s_seq) || *cancel) ); } /* check what happened */ if (-ERESTARTSYS == res) return ACH_EINTR; if( res < 0 ) { ACH_ERRF("ach bug: rdlock_wait(), " "could not wait for event, " "timeout: (%lu,%ld), result=%d\n", reltime->tv_sec, reltime->tv_nsec, res); return ACH_BUG; } r = chan_lock( chan ); /* Check condition with the lock held in case someone * else flushed the channel, or someone else unset the * cancel */ if( (*c_seq != *s_seq) || (ACH_OK != r) || *cancel ) { return r; } rt_mutex_unlock(&shm->sync.mutex); } }
static unsigned int ach_ch_poll(struct file *file, poll_table * wait) { unsigned int mask = POLLOUT | POLLWRNORM; struct ach_ch_file *ch_file = (struct ach_ch_file *)file->private_data; struct ach_header *shm = ch_file->shm; enum ach_status r; /* KDEBUG1("In ach_ch_poll (minor=%d)\n", ch_file->dev->minor); */ /* Add ourselves wait queue */ poll_wait(file, &shm->sync.readq, wait); /* Lock channel and check what happened */ r = chan_lock(ch_file); if( ACH_OK != r ) return -get_errno(r); if (ch_file->seq_num != shm->last_seq) { mask |= POLLIN | POLLRDNORM; } rt_mutex_unlock(&shm->sync.mutex); return mask; }
static enum ach_status rdlock(ach_channel_t * chan, int wait, const struct timespec *reltime) { if( wait ) return rdlock_wait(chan, reltime); else return chan_lock(chan); }