Print this page
OS-???? [lx] SIGEV_THREAD_ID emulation needed

@@ -988,10 +988,63 @@
                 }
 
                 return (0);
         }
 
+        case B_SIGEV_THREAD_ID: {
+                /*
+                 * Emulate Linux's timer_create(2) SIGEV_THREAD_ID
+                 * notification method. This mechanism is only meant
+                 * for userland threading libraries such as glibc and
+                 * is documented as such. Therefore, assume this is
+                 * only ever invoked for the purpose of alerting a
+                 * Linux threading library. Assume that the tid is a
+                 * member of the caller's process and the signal
+                 * number is valid. See lx_sigev_thread_id() for the
+                 * userland side of this emulation.
+                 *
+                 * The return code from this function is not checked
+                 * by the caller since it executes in an asynchronous
+                 * context and there is nothing much to be done. If
+                 * this function does fail then it will manifest as
+                 * Linux threads waiting for a signal they will never
+                 * receive.
+                 *
+                 * arg1 -- Linux tid
+                 * arg2 -- signal number
+                 * arg3 -- union sigval
+                 */
+
+                int native_sig = lx_stol_signo((int)arg2, LX_SIGTIMER);
+                pid_t native_pid;
+                int native_tid;
+                sigqueue_t *sqp;
+
+                lx_lpid_to_spair((pid_t)arg1, &native_pid, &native_tid);
+                sqp = kmem_zalloc(sizeof (sigqueue_t), KM_SLEEP);
+                mutex_enter(&curproc->p_lock);
+
+                if ((t = idtot(curproc, native_tid)) == NULL) {
+                        mutex_exit(&curproc->p_lock);
+                        kmem_free(sqp, sizeof (sigqueue_t));
+                        return (ESRCH);
+                }
+
+                sqp->sq_info.si_signo = native_sig;
+                sqp->sq_info.si_code = SI_TIMER;
+                sqp->sq_info.si_pid = curproc->p_pid;
+                sqp->sq_info.si_zoneid = getzoneid();
+                sqp->sq_info.si_uid = crgetruid(CRED());
+                sqp->sq_info.si_value = (union sigval)((void *)arg3);
+                sigaddqa(curproc, t, sqp);
+
+                mutex_exit(&curproc->p_lock);
+                kmem_free(sqp, sizeof (sigqueue_t));
+
+                return (0);
+        }
+
         case B_SET_AFFINITY_MASK:
         case B_GET_AFFINITY_MASK:
                 /*
                  * Retrieve or store the CPU affinity mask for the
                  * requested linux pid.