/* Copyright (C) 2014 Stony Brook University This file is part of Graphene Library OS. Graphene Library OS is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Graphene Library OS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ /* * shim_sleep.c * * Implementation of system call "pause" and "nanosleep". */ #include #include #include #include #include #include #include #include #include static bool signal_pending (void) { struct shim_thread* cur = get_cur_thread(); if (!cur) return false; lock(&cur->lock); if (!cur->signal_logs || !cur->has_signal.counter) { unlock(&cur->lock); return false; } for (int sig = 1; sig <= NUM_SIGS; sig++) { if (atomic_read(&cur->signal_logs[sig - 1].head) != atomic_read(&cur->signal_logs[sig - 1].tail)) { /* at least one signal of type sig... */ if (!__sigismember(&cur->signal_mask, sig)) { /* ...and this type is not blocked */ unlock(&cur->lock); return true; } } } unlock(&cur->lock); return false; } int shim_do_pause (void) { if (signal_pending()) return -EINTR; /* ~0ULL micro sec ~= 805675 years */ DkThreadDelayExecution(~((PAL_NUM)0)); return -EINTR; } int shim_do_nanosleep (const struct __kernel_timespec * rqtp, struct __kernel_timespec * rmtp) { if (!rqtp) return -EFAULT; if (signal_pending()) { if (rmtp) { /* no time elapsed, so copy time interval from rqtp to rmtp */ rmtp->tv_sec = rqtp->tv_sec; rmtp->tv_nsec = rqtp->tv_nsec; } return -EINTR; } unsigned long time = rqtp->tv_sec * 1000000L + rqtp->tv_nsec / 1000; unsigned long ret = DkThreadDelayExecution(time); if (ret < time) { if (rmtp) { unsigned long remtime = time - ret; rmtp->tv_sec = remtime / 1000000L; rmtp->tv_nsec = (remtime - rmtp->tv_sec * 1000) * 1000; } return -EINTR; } return 0; }