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

@@ -988,10 +988,61 @@
                 }
 
                 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.
+                 *
+                 * arg1 -- Linux tid
+                 * arg2 -- signal number
+                 * arg3 -- union sigval
+                 */
+
+                proc_t *pp, *cp = curproc;
+                int native_sig = ltos_signo[(int)arg2];
+                pid_t native_pid;
+                int native_tid;
+                sigqueue_t *sqp;
+
+                lx_lpid_to_spair((pid_t)arg1, &native_pid, &native_tid);
+
+                mutex_enter(&pidlock);
+                if (((pp = prfind(native_pid)) == NULL) || (pp->p_stat == SIDL)) {
+                        mutex_exit(&pidlock);
+                        return (ESRCH);
+                }
+                mutex_enter(&pp->p_lock);
+                mutex_exit(&pidlock);
+
+                if ((t = idtot(pp, native_tid)) == NULL) {
+                        mutex_exit(&pp->p_lock);
+                        return (ESRCH);
+                }
+
+                sqp = kmem_zalloc(sizeof (sigqueue_t), KM_SLEEP);
+                sqp->sq_info.si_signo = native_sig;
+                sqp->sq_info.si_code = SI_TIMER;
+                sqp->sq_info.si_pid = cp->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(pp, t, sqp);
+
+                mutex_exit(&pp->p_lock);
+                return (0);
+        }
+
         case B_SET_AFFINITY_MASK:
         case B_GET_AFFINITY_MASK:
                 /*
                  * Retrieve or store the CPU affinity mask for the
                  * requested linux pid.