I have futexes (as a way to implement critical sections in user-space), but they have some serious drawbacks in this scenario. First, the futex implies that each release of the futex will wakeup a single thread, but if two threads are waiting for the data to become available, only one of them will be woken up and the other one will be left blocked. The other drawback is that a futex must always be allocated and associated with the struct, which slows down the code. Particularly since multiple threads generally will not try to read the same directory, and so this is an exceptional case. Also, there will be an issue with freeing the futex too, and making sure that a thread will not try to use the futex while it is freed. In general, my usage of futexes does not really garantee problem-free behavior when futexes are freed, rather implies that the code makes sure that they are only freed when they cannot be referenced.
So, my take on this is like this:
Code:
for (;;)
{
if (ref_count >= 0)
{
if (pointer)
return pointer;
lock ref_count--;
if (CY)
{
pointer = ReadTheEntry();
lock ref_count++;
while (wait_count != 0)
Yield();
ebx = 0;
xchg ebx,wait
if (ebx)
CloseThreadBlock(ebx);
return pointer;
}
else
lock ref_count++;
}
else
{
if (!wait)
{
lock wait_count--;
if (CY)
wait = CreateThreadBlock();
lock wait_count++;
}
if (wait)
WaitThreadBlock(wait);
else
Yield();
}
}
CreateThreadBlock will create a handle that is backed with a list in kernel space. WaitThreadBlock will block a thread on the list, unless the handle is freed. CloseThreadBlock will inactivate the handle, wakeup waiting threads and then free it.
Edited the code many times, but I'm still not sure if it is multicore safe.