| 1180 | } |
| 1181 | |
| 1182 | int |
| 1183 | kern_ktimer_create(struct thread *td, clockid_t clock_id, struct sigevent *evp, |
| 1184 | int *timerid, int preset_id) |
| 1185 | { |
| 1186 | struct proc *p = td->td_proc; |
| 1187 | struct itimer *it; |
| 1188 | int id; |
| 1189 | int error; |
| 1190 | |
| 1191 | if (clock_id < 0 || clock_id >= MAX_CLOCKS) |
| 1192 | return (EINVAL); |
| 1193 | |
| 1194 | if (posix_clocks[clock_id].timer_create == NULL) |
| 1195 | return (EINVAL); |
| 1196 | |
| 1197 | if (evp != NULL) { |
| 1198 | if (evp->sigev_notify != SIGEV_NONE && |
| 1199 | evp->sigev_notify != SIGEV_SIGNAL && |
| 1200 | evp->sigev_notify != SIGEV_THREAD_ID) |
| 1201 | return (EINVAL); |
| 1202 | if ((evp->sigev_notify == SIGEV_SIGNAL || |
| 1203 | evp->sigev_notify == SIGEV_THREAD_ID) && |
| 1204 | !_SIG_VALID(evp->sigev_signo)) |
| 1205 | return (EINVAL); |
| 1206 | } |
| 1207 | |
| 1208 | if (p->p_itimers == NULL) |
| 1209 | itimers_alloc(p); |
| 1210 | |
| 1211 | it = uma_zalloc(itimer_zone, M_WAITOK); |
| 1212 | it->it_flags = 0; |
| 1213 | it->it_usecount = 0; |
| 1214 | it->it_active = 0; |
| 1215 | timespecclear(&it->it_time.it_value); |
| 1216 | timespecclear(&it->it_time.it_interval); |
| 1217 | it->it_overrun = 0; |
| 1218 | it->it_overrun_last = 0; |
| 1219 | it->it_clockid = clock_id; |
| 1220 | it->it_timerid = -1; |
| 1221 | it->it_proc = p; |
| 1222 | ksiginfo_init(&it->it_ksi); |
| 1223 | it->it_ksi.ksi_flags |= KSI_INS | KSI_EXT; |
| 1224 | error = CLOCK_CALL(clock_id, timer_create, (it)); |
| 1225 | if (error != 0) |
| 1226 | goto out; |
| 1227 | |
| 1228 | PROC_LOCK(p); |
| 1229 | if (preset_id != -1) { |
| 1230 | KASSERT(preset_id >= 0 && preset_id < 3, ("invalid preset_id")); |
| 1231 | id = preset_id; |
| 1232 | if (p->p_itimers->its_timers[id] != NULL) { |
| 1233 | PROC_UNLOCK(p); |
| 1234 | error = 0; |
| 1235 | goto out; |
| 1236 | } |
| 1237 | } else { |
| 1238 | /* |
| 1239 | * Find a free timer slot, skipping those reserved |
no test coverage detected