mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-05-09 11:12:51 -06:00
now we use inter-process locking
This commit is contained in:
@@ -7,6 +7,7 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
|
#include "ipc.h"
|
||||||
|
|
||||||
PGF_INTERNAL __thread unsigned char* current_base __attribute__((tls_model("initial-exec"))) = NULL;
|
PGF_INTERNAL __thread unsigned char* current_base __attribute__((tls_model("initial-exec"))) = NULL;
|
||||||
PGF_INTERNAL __thread PgfDB* current_db __attribute__((tls_model("initial-exec"))) = NULL;
|
PGF_INTERNAL __thread PgfDB* current_db __attribute__((tls_model("initial-exec"))) = NULL;
|
||||||
@@ -344,12 +345,12 @@ PgfDB::PgfDB(const char* filepath, int flags, int mode) {
|
|||||||
throw pgf_systemerror(code, filepath);
|
throw pgf_systemerror(code, filepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
int res = pthread_rwlock_init(&rwlock, NULL);
|
try {
|
||||||
if (res != 0) {
|
rwlock = ipc_new_file_rwlock(this->filepath);
|
||||||
|
} catch (pgf_systemerror e) {
|
||||||
::free((void *) this->filepath);
|
::free((void *) this->filepath);
|
||||||
int code = errno;
|
|
||||||
close(fd);
|
close(fd);
|
||||||
throw pgf_systemerror(code);
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_new) {
|
if (is_new) {
|
||||||
@@ -389,7 +390,7 @@ PgfDB::~PgfDB() {
|
|||||||
if (fd >= 0)
|
if (fd >= 0)
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
pthread_rwlock_destroy(&rwlock);
|
ipc_release_file_rwlock(filepath, rwlock);
|
||||||
|
|
||||||
::free((void*) filepath);
|
::free((void*) filepath);
|
||||||
}
|
}
|
||||||
@@ -1108,8 +1109,8 @@ void PgfDB::sync()
|
|||||||
DB_scope::DB_scope(PgfDB *db, DB_scope_mode m)
|
DB_scope::DB_scope(PgfDB *db, DB_scope_mode m)
|
||||||
{
|
{
|
||||||
int res =
|
int res =
|
||||||
(m == READER_SCOPE) ? pthread_rwlock_rdlock(&db->rwlock)
|
(m == READER_SCOPE) ? pthread_rwlock_rdlock(db->rwlock)
|
||||||
: pthread_rwlock_wrlock(&db->rwlock);
|
: pthread_rwlock_wrlock(db->rwlock);
|
||||||
if (res != 0)
|
if (res != 0)
|
||||||
throw pgf_systemerror(res);
|
throw pgf_systemerror(res);
|
||||||
|
|
||||||
@@ -1125,9 +1126,7 @@ DB_scope::~DB_scope()
|
|||||||
{
|
{
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wterminate"
|
#pragma GCC diagnostic ignored "-Wterminate"
|
||||||
int res = pthread_rwlock_unlock(¤t_db->rwlock);
|
pthread_rwlock_unlock(current_db->rwlock);
|
||||||
if (res != 0)
|
|
||||||
throw pgf_systemerror(res);
|
|
||||||
|
|
||||||
current_db = save_db;
|
current_db = save_db;
|
||||||
current_base = current_db ? (unsigned char*) current_db->ms
|
current_base = current_db ? (unsigned char*) current_db->ms
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ private:
|
|||||||
const char *filepath;
|
const char *filepath;
|
||||||
malloc_state* ms;
|
malloc_state* ms;
|
||||||
|
|
||||||
pthread_rwlock_t rwlock;
|
pthread_rwlock_t *rwlock;
|
||||||
|
|
||||||
friend class PgfReader;
|
friend class PgfReader;
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,15 @@ static file_locks *locks = NULL;
|
|||||||
PGF_INTERNAL
|
PGF_INTERNAL
|
||||||
pthread_rwlock_t *ipc_new_file_rwlock(const char* file_path)
|
pthread_rwlock_t *ipc_new_file_rwlock(const char* file_path)
|
||||||
{
|
{
|
||||||
|
if (file_path == NULL) {
|
||||||
|
pthread_rwlock_t *rwlock = (pthread_rwlock_t *)
|
||||||
|
malloc(sizeof(pthread_rwlock_t));
|
||||||
|
if (pthread_rwlock_init(rwlock, NULL) != 0) {
|
||||||
|
ipc_error();
|
||||||
|
}
|
||||||
|
return rwlock;
|
||||||
|
}
|
||||||
|
|
||||||
int pagesize = getpagesize();
|
int pagesize = getpagesize();
|
||||||
|
|
||||||
if (locks == NULL) {
|
if (locks == NULL) {
|
||||||
@@ -161,21 +170,54 @@ pthread_rwlock_t *ipc_new_file_rwlock(const char* file_path)
|
|||||||
entry->next = locks->lock_entries;
|
entry->next = locks->lock_entries;
|
||||||
locks->lock_entries = offs(entry);
|
locks->lock_entries = offs(entry);
|
||||||
} else {
|
} else {
|
||||||
process_entry *pentry;
|
process_entry *pentry = &entry->p;
|
||||||
if (locks->free_process_entries) {
|
ptr_t(process_entry) *plast = NULL;
|
||||||
pentry = ptr(locks->free_process_entries,process_entry);
|
while (pentry != NULL) {
|
||||||
locks->free_process_entries = pentry->next;
|
char proc_file[32];
|
||||||
} else {
|
sprintf(proc_file, "/proc/%d", pentry->pid);
|
||||||
if (locks->top+sizeof(process_entry) > pagesize) {
|
if (access(proc_file, F_OK) != 0) {
|
||||||
pthread_mutex_unlock(&locks->mutex);
|
// if there are dead processes -> remove them
|
||||||
ipc_toomany();
|
if (plast == NULL) {
|
||||||
|
if (entry->p.next == 0) {
|
||||||
|
entry->p.pid = 0;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
process_entry *tmp =
|
||||||
|
ptr(pentry->next, process_entry);
|
||||||
|
*pentry = *tmp;
|
||||||
|
tmp->pid = 0;
|
||||||
|
tmp->next = locks->free_process_entries;
|
||||||
|
locks->free_process_entries = offs(tmp);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*plast = pentry->next;
|
||||||
|
pentry->pid = 0;
|
||||||
|
pentry->next = locks->free_process_entries;
|
||||||
|
locks->free_process_entries = offs(pentry);
|
||||||
|
pentry = ptr(*plast,process_entry);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
plast = &pentry->next;
|
||||||
|
pentry = ptr(*plast,process_entry);
|
||||||
}
|
}
|
||||||
pentry = ptr(locks->top,process_entry);
|
|
||||||
locks->top += sizeof(process_entry);
|
|
||||||
}
|
}
|
||||||
pentry->next = entry->p.next;
|
|
||||||
pentry->pid = getpid();
|
if (plast != NULL) {
|
||||||
entry->p.next = offs(pentry);
|
if (locks->free_process_entries) {
|
||||||
|
pentry = ptr(locks->free_process_entries,process_entry);
|
||||||
|
locks->free_process_entries = pentry->next;
|
||||||
|
} else {
|
||||||
|
if (locks->top+sizeof(process_entry) > pagesize) {
|
||||||
|
pthread_mutex_unlock(&locks->mutex);
|
||||||
|
ipc_toomany();
|
||||||
|
}
|
||||||
|
pentry = ptr(locks->top,process_entry);
|
||||||
|
locks->top += sizeof(process_entry);
|
||||||
|
}
|
||||||
|
*plast = offs(pentry);
|
||||||
|
}
|
||||||
|
pentry->pid = getpid();
|
||||||
|
pentry->next = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_unlock(&locks->mutex);
|
pthread_mutex_unlock(&locks->mutex);
|
||||||
@@ -184,8 +226,15 @@ pthread_rwlock_t *ipc_new_file_rwlock(const char* file_path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
PGF_INTERNAL
|
PGF_INTERNAL
|
||||||
void ipc_release_file_rwlock(const char* file_path)
|
void ipc_release_file_rwlock(const char* file_path,
|
||||||
|
pthread_rwlock_t *rwlock)
|
||||||
{
|
{
|
||||||
|
if (file_path == NULL) {
|
||||||
|
pthread_rwlock_destroy(rwlock);
|
||||||
|
free(rwlock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (locks == NULL)
|
if (locks == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -228,6 +277,7 @@ free_it:
|
|||||||
process_entry *tmp =
|
process_entry *tmp =
|
||||||
ptr(pentry->next, process_entry);
|
ptr(pentry->next, process_entry);
|
||||||
*pentry = *tmp;
|
*pentry = *tmp;
|
||||||
|
tmp->pid = 0;
|
||||||
tmp->next = locks->free_process_entries;
|
tmp->next = locks->free_process_entries;
|
||||||
locks->free_process_entries = offs(tmp);
|
locks->free_process_entries = offs(tmp);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ PGF_INTERNAL_DECL
|
|||||||
pthread_rwlock_t *ipc_new_file_rwlock(const char* file_path);
|
pthread_rwlock_t *ipc_new_file_rwlock(const char* file_path);
|
||||||
|
|
||||||
PGF_INTERNAL
|
PGF_INTERNAL
|
||||||
void ipc_release_file_rwlock(const char* file_path);
|
void ipc_release_file_rwlock(const char* file_path,
|
||||||
|
pthread_rwlock_t *rwlock);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user