mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 04:43:03 +01:00
Rewiev semaphore on Solaris platform:
add some fixes and loop on EINTR
This commit is contained in:
parent
ceb24dab6a
commit
6b86285492
@ -79,14 +79,19 @@ public:
|
||||
1) Old (~1985) troubles reported to Borland about semaphores on Solaris
|
||||
2) No gds_lock_manager
|
||||
3) No sem_timedwait on Solaris
|
||||
4) thread functions does not garantie setting errno 12 apr 2006
|
||||
Readings is:
|
||||
1) http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libpthread/thread/thr_sem.c?rev=1.15
|
||||
2) http://docs.sun.com/app/docs/doc/802-5747-03/6i9g1bhqp?a=view
|
||||
3) http://docs.sun.com/app/docs/doc/802-5938?a=expand
|
||||
|
||||
Konstantin
|
||||
Status:
|
||||
12 apr 2006 add looping if EINTR caused
|
||||
Still under testings
|
||||
Konstantin Kuznetsov kkuznetsov at the users of the sf net
|
||||
|
||||
|
||||
thank's to Claudio ...
|
||||
*/
|
||||
*/
|
||||
#include <thread.h>
|
||||
#include <synch.h>
|
||||
|
||||
@ -97,33 +102,40 @@ namespace Firebird {
|
||||
|
||||
class Semaphore {
|
||||
private:
|
||||
mutex_t mu;
|
||||
cond_t cv;
|
||||
bool init;
|
||||
mutex_t mu;
|
||||
cond_t cv;
|
||||
bool init;
|
||||
int err; //thread functions does not garantie setting errno
|
||||
public:
|
||||
Semaphore() : init(false) {
|
||||
/* USINC_PROCESS got ability to syncronise Classic
|
||||
*/
|
||||
if ( mutex_init(&mu, USYNC_PROCESS, NULL) != 0) {
|
||||
err = 0;
|
||||
err = mutex_init(&mu, USYNC_PROCESS, NULL);
|
||||
if (err != 0) {
|
||||
//gds__log("Error on semaphore.h: constructor");
|
||||
system_call_failed::raise("mutex_init");
|
||||
system_call_failed::raise("mutex_init", err);
|
||||
}
|
||||
if (cond_init(&cv, USYNC_PROCESS, NULL) != 0) {
|
||||
err = cond_init(&cv, USYNC_PROCESS, NULL);
|
||||
if ( err != 0) {
|
||||
//gds__log("Error on semaphore.h: constructor");
|
||||
system_call_failed::raise("cond_init");
|
||||
system_call_failed::raise("cond_init",err);
|
||||
}
|
||||
init = true;
|
||||
}
|
||||
|
||||
~Semaphore() {
|
||||
fb_assert(init == true);
|
||||
if (mutex_destroy(&mu) != 0) {
|
||||
err = 0;
|
||||
err = mutex_destroy(&mu);
|
||||
if (err != 0) {
|
||||
//gds__log("Error on semaphore.h: destructor");
|
||||
system_call_failed::raise("mutex_destroy");
|
||||
system_call_failed::raise("mutex_destroy",err);
|
||||
}
|
||||
if (cond_destroy(&cv) != 0) {
|
||||
err = cond_destroy(&cv);
|
||||
if (err != 0) {
|
||||
//gds__log("Error on semaphore.h: destructor");
|
||||
system_call_failed::raise("cond_destroy");
|
||||
system_call_failed::raise("cond_destroy",err);
|
||||
}
|
||||
|
||||
init = false;
|
||||
@ -132,109 +144,124 @@ public:
|
||||
|
||||
bool tryEnter(int seconds = 0) {
|
||||
bool rt = false;
|
||||
int err2 = 0;
|
||||
// Return true in case of success
|
||||
fb_assert(init == true);
|
||||
if (seconds == 0) {
|
||||
// Instant try
|
||||
if (mutex_trylock(&mu) != 0) {
|
||||
|
||||
if (cond_wait(&cv, &mu) != 0) {
|
||||
rt = false;
|
||||
|
||||
}
|
||||
else
|
||||
rt = true;
|
||||
if (errno == ETIMEDOUT)
|
||||
err2 = mutex_trylock(&mu);
|
||||
if (err2 != 0) {
|
||||
do {
|
||||
err = cond_wait(&cv, &mu);
|
||||
if (err != 0) {
|
||||
rt = false;
|
||||
}
|
||||
else
|
||||
rt = true;
|
||||
} while (err == EINTR);
|
||||
if (err == ETIMEDOUT)
|
||||
rt = false;
|
||||
|
||||
mutex_unlock(&mu);
|
||||
return rt;
|
||||
}
|
||||
else if (errno == EBUSY) {
|
||||
else if (err2 == EBUSY) {
|
||||
rt = false;
|
||||
return rt;
|
||||
}
|
||||
|
||||
system_call_failed::raise("mutex_lock");
|
||||
system_call_failed::raise("mutex_trylock", err2);
|
||||
}
|
||||
if (seconds < 0) {
|
||||
// Unlimited wait, like enter()
|
||||
if (mutex_lock(&mu) != 0) {
|
||||
|
||||
if (cond_wait(&cv, &mu) != 0) {
|
||||
rt = false;
|
||||
}
|
||||
else
|
||||
rt = true;
|
||||
|
||||
if (errno == ETIMEDOUT)
|
||||
err2 = mutex_lock(&mu);
|
||||
if (err2 != 0) {
|
||||
do {
|
||||
err = cond_wait(&cv, &mu);
|
||||
if (err != 0) {
|
||||
rt = false;
|
||||
}
|
||||
else
|
||||
rt = true;
|
||||
} while (err == EINTR);
|
||||
if (err == ETIMEDOUT)
|
||||
rt = false;
|
||||
|
||||
mutex_unlock(&mu);
|
||||
return rt;
|
||||
}
|
||||
else if (errno == EBUSY) {
|
||||
else if (err2 == EBUSY) {
|
||||
rt = false;
|
||||
return rt;
|
||||
}
|
||||
else
|
||||
system_call_failed::raise("mutex_lock");
|
||||
system_call_failed::raise("mutex_lock", err2);
|
||||
|
||||
}
|
||||
} //seconds < 0
|
||||
// Wait with timeout
|
||||
timestruc_t timeout;
|
||||
timeout.tv_sec = time(NULL) + seconds;
|
||||
timeout.tv_nsec = 0;
|
||||
if (mutex_lock(&mu) != 0) {
|
||||
|
||||
if (cond_timedwait(&cv, &mu, &timeout) != 0) {
|
||||
rt = false;
|
||||
}
|
||||
else
|
||||
rt = true;
|
||||
if (errno == ETIMEDOUT)
|
||||
err2 = mutex_lock(&mu) ;
|
||||
if (err2 != 0) {
|
||||
do {
|
||||
err = cond_timedwait(&cv, &mu, &timeout);
|
||||
if (err != 0) {
|
||||
rt = false;
|
||||
}
|
||||
else
|
||||
rt = true;
|
||||
} while (err == EINTR);
|
||||
if (err == ETIMEDOUT)
|
||||
rt = false;
|
||||
|
||||
mutex_unlock(&mu);
|
||||
return rt;
|
||||
}
|
||||
else if (errno == EBUSY) {
|
||||
else if (err2 == EBUSY) {
|
||||
rt = false;
|
||||
return rt;
|
||||
}
|
||||
else
|
||||
system_call_failed::raise("mutex_lock");
|
||||
system_call_failed::raise("mutex_lock", err2);
|
||||
}
|
||||
|
||||
void enter() {
|
||||
fb_assert(init == true);
|
||||
if (mutex_lock(&mu) != 0) {
|
||||
|
||||
if (cond_wait(&cv, &mu) != 0) {
|
||||
}
|
||||
// Is the above if() meant to be empty?
|
||||
int err2 = 0;
|
||||
err2 = mutex_lock(&mu);
|
||||
if (err2 != 0) {
|
||||
do {
|
||||
err = cond_wait(&cv, &mu);
|
||||
if (err == 0) {
|
||||
break;
|
||||
}
|
||||
} while (err == EINTR);
|
||||
|
||||
mutex_unlock(&mu);
|
||||
}
|
||||
else
|
||||
system_call_failed::raise("mutex_lock");
|
||||
system_call_failed::raise("mutex_lock", err2);
|
||||
|
||||
}
|
||||
|
||||
void release(SLONG count = 1) {
|
||||
int err2 = 0;
|
||||
fb_assert(init == true);
|
||||
for (int i = 0; i < count; i++)
|
||||
|
||||
if (mutex_lock(&mu) != 0) {
|
||||
|
||||
if (cond_broadcast(&cv) != 0) {
|
||||
system_call_failed::raise("cond_signal");
|
||||
err2 = mutex_lock(&mu) ;
|
||||
if (err2 != 0) {
|
||||
err = cond_broadcast(&cv);
|
||||
if (err != 0) {
|
||||
system_call_failed::raise("cond_signal", err);
|
||||
}
|
||||
|
||||
mutex_unlock(&mu);
|
||||
}
|
||||
else {
|
||||
//gds__log("Error on semaphore.h: release");
|
||||
system_call_failed::raise("mutex_lock");
|
||||
system_call_failed::raise("mutex_lock", err2);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user