Print this page
OS-???? [lx] SIGEV_THREAD_ID emulation needed
*** 23,33 ****
--- 23,36 ----
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2015 Joyent, Inc.
*/
+ #include <sys/syscall.h>
+
#include <errno.h>
+ #include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/resource.h>
#include <sys/lx_misc.h>
#include <sys/lx_syscall.h>
*** 105,124 ****
void *lx_notify_attribute;
} lx_sigev_thread;
} lx_sigev_un;
} lx_sigevent_t;
/* sigevent sigev_notify conversion table */
static int ltos_sigev[] = {
SIGEV_SIGNAL,
SIGEV_NONE,
SIGEV_THREAD,
0, /* Linux skips event 3 */
! SIGEV_THREAD /* the Linux SIGEV_THREAD_ID */
};
#define LX_SIGEV_MAX (sizeof (ltos_sigev) / sizeof (ltos_sigev[0]))
long
lx_clock_nanosleep(int clock, int flags, struct timespec *rqtp,
struct timespec *rmtp)
{
--- 108,130 ----
void *lx_notify_attribute;
} lx_sigev_thread;
} lx_sigev_un;
} lx_sigevent_t;
+ #define lx_sigev_notify_attributes lx_sigev_un.lx_sigev_thread.lx_notify_attribute
+
/* sigevent sigev_notify conversion table */
static int ltos_sigev[] = {
SIGEV_SIGNAL,
SIGEV_NONE,
SIGEV_THREAD,
0, /* Linux skips event 3 */
! SIGEV_THREAD /* Linux SIGEV_THREAD_ID -- see lx_sigev_thread_id() */
};
#define LX_SIGEV_MAX (sizeof (ltos_sigev) / sizeof (ltos_sigev[0]))
+ #define LX_SIGEV_THREAD_ID 4
long
lx_clock_nanosleep(int clock, int flags, struct timespec *rqtp,
struct timespec *rmtp)
{
*** 161,170 ****
--- 167,192 ----
{
return (-EPERM);
}
/*
+ * Notification function for use with native SIGEV_THREAD in order to
+ * emulate Linux SIGEV_THREAD_ID. Native SIGEV_THREAD is used as the
+ * timer mechanism and B_SIGEV_THREAD_ID performs the actual event
+ * delivery to the appropriate lx tid.
+ */
+ static void
+ lx_sigev_thread_id(union sigval sival)
+ {
+ lx_sigevent_t *lev = (lx_sigevent_t *)sival.sival_ptr;
+ syscall(SYS_brand, B_SIGEV_THREAD_ID, lev->lx_sigev_un.lx_tid,
+ lev->lx_sigev_signo, lev->lx_sigev_value);
+ free(lev);
+ }
+
+
+ /*
* The Illumos timer_create man page says it accepts the following clocks:
* CLOCK_REALTIME (3) wall clock
* CLOCK_VIRTUAL (1) user CPU usage clock - No Backend
* CLOCK_PROF (2) user and system CPU usage clock - No Backend
* CLOCK_HIGHRES (4) non-adjustable, high-resolution clock
*** 191,204 ****
sev.sigev_notify = ltos_sigev[lev.lx_sigev_notify];
sev.sigev_signo = ltos_signo[lev.lx_sigev_signo];
sev.sigev_value = lev.lx_sigev_value;
/*
! * The sigevent sigev_notify_function and sigev_notify_attributes
! * members are not used by timer_create, so no conversion is needed.
*/
return ((timer_create(ltos_timer[clock], &sev, tid) < 0) ? -errno : 0);
}
long
lx_timer_settime(timer_t tid, int flags, struct itimerspec *new_val,
--- 213,244 ----
sev.sigev_notify = ltos_sigev[lev.lx_sigev_notify];
sev.sigev_signo = ltos_signo[lev.lx_sigev_signo];
sev.sigev_value = lev.lx_sigev_value;
/*
! * Assume all Linux libc implementations map SIGEV_THREAD to
! * SIGEV_THREAD_ID and ignore passed-in attributes.
*/
+ sev.sigev_notify_attributes = NULL;
+ if (lev.lx_sigev_notify == LX_SIGEV_THREAD_ID) {
+ /*
+ * Pass the original lx sigevent_t to the native
+ * notify function so that it may pass it to the lx
+ * helper thread.
+ */
+ lx_sigevent_t *lev_copy = malloc(sizeof (lx_sigevent_t));
+ if (lev_copy == NULL)
+ return (-ENOMEM);
+
+ if (uucopy(&lev, lev_copy, sizeof (lx_sigevent_t)) < 0)
+ return (-EFAULT);
+
+ sev.sigev_notify_function = lx_sigev_thread_id;
+ sev.sigev_value.sival_ptr = lev_copy;
+ }
+
return ((timer_create(ltos_timer[clock], &sev, tid) < 0) ? -errno : 0);
}
long
lx_timer_settime(timer_t tid, int flags, struct itimerspec *new_val,