Re: Using MIG RPC between 2 threads inside a process
Re: Using MIG RPC between 2 threads inside a process
- Subject: Re: Using MIG RPC between 2 threads inside a process
- From: Godfrey van der Linden <email@hidden>
- Date: Thu, 16 Sep 2004 14:11:41 -0700
Oops, sorry I forgot to signal the condition in enqueue should read
void enqueue: (queue_entry_t) record
{
// Note no allocation to hold us up - it is assumed that the client
has done the allocation itself
pthread_mutex_lock(&queueLock);
enqueue(&queueHead, record);
pthread_cond_signal(&queueSleeper);
pthread_mutex_unlock(&queueLock);
}
Also a small optimisation would be to track if you have any sleepers
behind the dequeue and only do a signal if sleepers > 0.
Godfrey
On Sep 16, , at 11:50, Stéphane Letz wrote:
Basically the solution is to use an internal queue protected by the
mutex and when there is no work to do you use a condition to block
the thread. (This is exactly what we do in the kernel a whole lot
;-)
It is most common to write the queue mechanism in a new class, if you
are doing OO. These queues are extraordinarily easy to write. This
general model is not only efficient but if you do it write the locks
on the queues are the only locks you need in your entire design.
I recommend that you don't allocate any storage in the queue insert
structure, rather your queue is only appending the argument data
structure on the end of a linked list. I usually use the
<kern/queue.h> macros for this, you can copy and paste the macros
into your new class from
/System/Library/Frameworks/Kernel.framework/Headers/kern/queue.h
Below is a rough cut at the implementation of the ObjC class for
queues based upon pthread locking and <kern/queue.h>.
@interface fr_grame_letz_Queue
{
pthread_mutex_t queueLock;
pthread_condition_t queueSleeper;
queue_head_t queueHead;
}
void enqueue: (queue_entry_t) record;
queue_entry_t dequeueAndBlock: (BOOL) block;
@end
@implementation fr_grame_letz_Queue
void enqueue: (queue_entry_t) record
{
// Note no allocation to hold us up - it is assumed that the
client has done the allocation itself
pthread_mutex_lock(&queueLock);
enqueue(&queueHead, record);
pthread_mutex_unlock(&queueLock);
}
queue_entry_t dequeueAndBlock: (BOOL) block
{
queue_entry_t ret = 0;
pthread_mutex_lock(&queueLock)
while (queue_empty(&queueHead)) {
if (!block)
goto abortDequeue;
pthread_cond_wait(&queueSleeper, &queueLock);
}
ret = dequeue(&queueHead);
abortDequeue:
pthread_mutex_unlock(&queueLock);
return 0;
}
I don't understand here : who is going to "signal" to condition
variable that there is something to read in the queue? Is it part of
the " enqueue(&queueHead, record);" operation?
@end
The above code is the guts of a queuer but you still have to write
the intialisation and teardown code. This basic model is very, very
common in the kernel and is remarkably efficient.
It works best when you combine the queue with the concept of
'ownership'. That is your 'client' thread allocates the 'record',
initialises it and enqueues it. It agrees that it is not allowed to
deal with the record until it gets returned to it on it's own queue,
the only function that is allowed to operate on it is an 'abort'
function if that is meaninngful.
Another problem for me is that the thread which has things to enqueue
is a time-constraint thread. I guess locking the pthread_mutex can
cause priority inversion problems that I can not afford.
This is why using this inter-thread *asynchonous* RPC mechanism, i was
thinking that I could also avoid the priority inversion problem.
Thanks
Stephane Letz
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden