#include "namespace.h"
#include <sys/cdefs.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <sys/upmap.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <pthread.h>
#include "un-namespace.h"
#include "libc_private.h"
#include "upmap.h"
static pthread_mutex_t ukpmap_lock;
static ukpheader_t *__kpmap_headers;
static ukpheader_t *__upmap_headers;
__thread ukpheader_t *__lpmap_headers TLS_ATTRIBUTE;
__thread uint32_t *__lpmap_blockallsigs TLS_ATTRIBUTE;
static __thread int lpmap_ok;
static int kpmap_ok;
static int upmap_ok;
static pthread_once_t upmap_once = PTHREAD_ONCE_INIT;
void
__kpmap_map(void *datap, int *state, uint16_t type)
{
ukpheader_t *head;
if (__isthreaded)
_pthread_mutex_lock(&ukpmap_lock);
if (kpmap_ok <= 0) {
int fd;
if (kpmap_ok < 0)
goto failed;
fd = _open("/dev/kpmap", O_RDONLY);
if (fd < 0) {
kpmap_ok = -1;
goto failed;
}
__kpmap_headers = mmap(NULL, KPMAP_MAPSIZE,
PROT_READ, MAP_SHARED | MAP_FILE,
fd, 0);
_close(fd);
if ((void *)__kpmap_headers == MAP_FAILED) {
kpmap_ok = -1;
goto failed;
}
kpmap_ok = 1;
}
if (type == 0) {
if (*state == 0)
*state = 1;
if (__isthreaded)
_pthread_mutex_unlock(&ukpmap_lock);
return;
}
for (head = __kpmap_headers; head->type; ++head) {
if (head->type == type) {
*(void **)datap = (char *)__kpmap_headers +
head->offset;
if (__isthreaded)
_pthread_mutex_unlock(&ukpmap_lock);
return;
}
}
failed:
*state = -1;
if (__isthreaded)
_pthread_mutex_unlock(&ukpmap_lock);
}
void
__upmap_map(void *datap, int *state, uint16_t type)
{
ukpheader_t *head;
if (__isthreaded)
_pthread_mutex_lock(&ukpmap_lock);
if (upmap_ok <= 0) {
int fd;
if (upmap_ok < 0)
goto failed;
fd = _open("/dev/upmap", O_RDWR);
if (fd < 0) {
upmap_ok = -1;
goto failed;
}
__upmap_headers = mmap(NULL, UPMAP_MAPSIZE,
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_FILE,
fd, 0);
_close(fd);
if ((void *)__upmap_headers == MAP_FAILED) {
upmap_ok = -1;
goto failed;
}
upmap_ok = 1;
}
if (type == 0) {
if (*state == 0)
*state = 1;
if (__isthreaded)
_pthread_mutex_unlock(&ukpmap_lock);
return;
}
for (head = __upmap_headers; head->type; ++head) {
if (head->type == type) {
*(void **)datap = (char *)__upmap_headers +
head->offset;
if (__isthreaded)
_pthread_mutex_unlock(&ukpmap_lock);
return;
}
}
failed:
*state = -1;
if (__isthreaded)
_pthread_mutex_unlock(&ukpmap_lock);
}
static pthread_key_t lpmap_key;
static void lpmap_unmap(void **datap);
void
__lpmap_map(void *datap, int *state, uint16_t type)
{
ukpheader_t *head;
if (lpmap_ok <= 0) {
int fd;
if (lpmap_ok < 0)
goto failed;
fd = _open("/dev/lpmap", O_RDWR);
if (fd < 0) {
lpmap_ok = -1;
goto failed;
}
__lpmap_headers = mmap(NULL, LPMAP_MAPSIZE,
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_FILE,
fd, 0);
_close(fd);
if ((void *)__lpmap_headers == MAP_FAILED) {
lpmap_ok = -1;
goto failed;
}
lpmap_ok = 1;
_pthread_setspecific(lpmap_key, &__lpmap_headers);
}
if (type == 0) {
if (*state == 0)
*state = 1;
return;
}
for (head = __lpmap_headers; head->type; ++head) {
if (head->type == type) {
*(void **)datap = (char *)__lpmap_headers +
head->offset;
return;
}
}
failed:
*state = -1;
}
static void
lpmap_unmap(void **datap)
{
ukpheader_t *lpmap = *datap;
lpmap_ok = -1;
if (lpmap) {
__lpmap_blockallsigs = NULL;
*datap = NULL;
munmap(lpmap, LPMAP_MAPSIZE);
}
}
static
void
_upmap_init_once(void)
{
_pthread_key_create(&lpmap_key, (void (*)(void *))lpmap_unmap);
}
void
_upmap_thr_init(void)
{
int dummy_state = 0;
_pthread_once(&upmap_once, _upmap_init_once);
__lpmap_map(&__lpmap_blockallsigs, &dummy_state, LPTYPE_BLOCKALLSIGS);
}