int setrunmask_remote(node_t node, pid_t pid, int tid, int *runmask, int inherit, int rsize_unsigned) { char *path; procfs_threadctl *threadctl; procfs_status status; int fd, ret, found, cmd, *rsizep, rsize_char, size; unsigned *rmaskp, *imaskp; procfs_run run; /* How many chars in each mask */ rsize_char = rsize_unsigned * sizeof(unsigned); size = offsetof(procfs_threadctl, data); /* * Out of _NTO_TCTL_RUNMASK*, a straight _NTO_TCTL_RUNMASK * works with the most old versions of proc. */ if (inherit == 0 && rsize_unsigned == 1) { cmd = _NTO_TCTL_RUNMASK; size += sizeof(unsigned); /* The mask */ } else { cmd = _NTO_TCTL_RUNMASK_GET_AND_SET_INHERIT; size += sizeof(int); /* rsize */ size += rsize_char; /* runmask */ size += rsize_char; /* inherit_mask */ } if ((threadctl = alloca(size)) == NULL) { errno = ENOMEM; return -1; } memset(threadctl, 0x00, size); threadctl->cmd = cmd; if (cmd == _NTO_TCTL_RUNMASK) { rmaskp = (unsigned *)threadctl->data; *rmaskp = *runmask; imaskp = NULL; rsizep = NULL; } else { rsizep = (int *)threadctl->data; *rsizep = rsize_unsigned; rmaskp = rsizep + 1; imaskp = rmaskp + rsize_unsigned; memcpy(rmaskp, runmask, rsize_char); if (inherit) memcpy(imaskp, runmask, rsize_char); else memset(imaskp, 0x00, rsize_char); } /* * _NTO_TCTL_RUNMASK* always needs O_RDWR so we can't fall * back to O_RDONLY like in setprio_remote(). */ if ((path = prepare_path(NULL, node, "/proc/%d/as", pid)) == NULL || (fd = open(path, O_RDWR)) == -1) return -1; if (tid != 0) { /* Set the specified thread */ threadctl->tid = tid; ret = _devctl(fd, DCMD_PROC_THREADCTL, threadctl, size, _DEVCTL_FLAG_NORETVAL); } else if (inherit == 0 || (ret = _devctl(fd, DCMD_PROC_STOP, NULL, 0, _DEVCTL_FLAG_NORETVAL)) != -1) { /* * Set all threads. DCMD_PROC_STOP issued for inherit * above so that none are missed. */ for (found = 0, status.tid = 1;; status.tid++) { if ((ret = _devctl(fd, DCMD_PROC_TIDSTATUS, &status, sizeof(status), _DEVCTL_FLAG_NORETVAL)) == -1) { if (errno == ESRCH && found) ret = 0; break; } threadctl->tid = status.tid; /* * Ignore ESRCH as the thread in question may have * exited since being found above. */ if ((ret = _devctl(fd, DCMD_PROC_THREADCTL, threadctl, size, _DEVCTL_FLAG_NORETVAL)) != -1) found = 1; else if (errno != ESRCH) break; if (cmd == _NTO_TCTL_RUNMASK_GET_AND_SET_INHERIT) { /* Reset since old masks are returned out */ memcpy(rmaskp, runmask, rsize_char); if (inherit) memcpy(imaskp, runmask, rsize_char); else memset(imaskp, 0x00, rsize_char); } } if (inherit != 0) { memset(&run, 0x00, sizeof(run)); if (_devctl(fd, DCMD_PROC_RUN, &run, sizeof(run), _DEVCTL_FLAG_NORETVAL) == -1) { /* Very bad */ perror("process restart failed"); ret = -1; } } } close(fd); return ret; }