/** * @file pthread-timedwait.c * @brief Demonstrates the effects on pthread_timedwait upon system wall clock * change */ #define _POSIX_C_SOURCE 199309L #include #include #include #include #include #include #define ARG0 "pthread_timedwait" struct { // desired sleep time struct timespec t; } opts; /** * @brief Raise nanosecond fraction part * @details "05" -> 50000000, "123" -> 123000000, "005" -> 5000000 * @note used to preserve precision * * @param str fraction part, excluding the leading decimal point * @param len length of \param str * @return long the fraction part raised to nanosecond scale */ long raise_nsec_frac (const char *str, const size_t len) { char m[] = { '0', '0', '0', '0', '0', '0', '0', '0', '0', 0 }; char *p; long ret = -1; memcpy(m, str, len > 9 ? 9 : len); for (p = m; *p != 0 && *p == '0'; p += 1); if (*p == 0 && m[0] == '0') { return 0; } if (sscanf(p, "%ld", &ret) != 1) { return -1; } return ret; } /** * @brief Parse timespec from string, preserving precision * * @param str string to parse * @param ts_out (optional) pointer to timespec struct * @return true if parsed successfully and \param ts_out is set if non-null * @return false otherwise. errno set to EINVAL if \param str is NULL. errno set * to EBADMSG on format error */ bool parse_ts (const char *str, struct timespec *ts_out) { long long sec = 0; long nsec = 0; int fr; const char *frac, *ipart; if (str == NULL) { errno = EINVAL; return false; } if (str[0] == '.' || str[0] == ',') { ipart = NULL; frac = str + 1; } else { ipart = str; frac = strchr(str, '.'); if (frac == NULL) { frac = strchr(str, ','); } } if (ipart != NULL) { fr = sscanf(ipart, "%lld", &sec); if (fr < 1) { errno = EBADMSG; return false; } } if (frac != NULL) { frac += 1; nsec = raise_nsec_frac(frac, strlen(frac)); if (nsec < 0) { errno = EBADMSG; return false; } } if (ts_out != NULL) { ts_out->tv_sec = sec; ts_out->tv_nsec = nsec; } return true; } bool parse_args (const int argc, const char **argv) { if (argc <= 1) { fprintf(stderr, ARG0"