diff --git a/net/socket/setsockopt.c b/net/socket/setsockopt.c index 61e502ddfd8..cc6d15dec9e 100644 --- a/net/socket/setsockopt.c +++ b/net/socket/setsockopt.c @@ -1,7 +1,7 @@ /**************************************************************************** * net/socket/setsockopt.c * - * Copyright (C) 2007, 2008, 2011-2012, 2014 Gregory Nutt. All rights + * Copyright (C) 2007, 2008, 2011-2012, 2014-2015 Gregory Nutt. All rights * reserved. * Author: Gregory Nutt * @@ -173,19 +173,22 @@ int psock_setsockopt(FAR struct socket *psock, int level, int option, case SO_RCVTIMEO: case SO_SNDTIMEO: { + FAR struct timeval *tv = (FAR struct timeval *)value; socktimeo_t timeo; /* Verify that option is the size of an 'struct timeval'. */ - if (value_len != sizeof(struct timeval)) + if (tv == NULL || value_len != sizeof(struct timeval)) { err = EINVAL; goto errout; } - /* Get the timeout value */ + /* Get the timeout value. Any microsecond remainder will be + * force to the next larger, whole decisecond value. + */ - timeo = (socktimeo_t)net_timeval2dsec((struct timeval *)value); + timeo = (socktimeo_t)net_timeval2dsec(tv, TV2DS_CEIL); /* Save the timeout value */ diff --git a/net/utils/net_timeval2dsec.c b/net/utils/net_timeval2dsec.c index b4beaf4eff2..a08a17e964f 100644 --- a/net/utils/net_timeval2dsec.c +++ b/net/utils/net_timeval2dsec.c @@ -1,7 +1,7 @@ /**************************************************************************** * net/utils/net_timeval2dsec.c * - * Copyright (C) 2007, 2008, 2014 Gregory Nutt. All rights reserved. + * Copyright (C) 2007, 2008, 2014-2015 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -57,7 +57,8 @@ * save new timeout values. * * Parameters: - * tv The struct timeval to convert + * tv - The struct timeval to convert + * remainder - Determines how to handler the microsecond remainder * * Returned Value: * The converted value @@ -66,7 +67,26 @@ * ****************************************************************************/ -unsigned int net_timeval2dsec(struct timeval *tv) +unsigned int net_timeval2dsec(FAR struct timeval *tv, + enum tv2ds_remainder_e remainder) { - return (unsigned int)(tv->tv_sec * DSEC_PER_SEC + tv->tv_usec / USEC_PER_DSEC); + unsigned long adjust = 0; + + switch (remainder) + { + default: + case TV2DS_TRUNC: /* Truncate microsecond remainder */ + break; + + case TV2DS_ROUND: /* Round to the nearest full decisecond */ + adjust = (USEC_PER_DSEC / 2); + break; + + case TV2DS_CEIL: /* Force to next larger full decisecond */ + adjust = (USEC_PER_DSEC - 1); + break; + } + + return (unsigned int)(tv->tv_sec * DSEC_PER_SEC + + (tv->tv_usec + adjust) / USEC_PER_DSEC); } diff --git a/net/utils/utils.h b/net/utils/utils.h index 3322f868bf4..951caf8d595 100644 --- a/net/utils/utils.h +++ b/net/utils/utils.h @@ -1,7 +1,7 @@ /**************************************************************************** * net/utils/utils.h * - * Copyright (C) 2014 Gregory Nutt. All rights reserved. + * Copyright (C) 2014-2015 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -51,6 +51,15 @@ * Public Types ****************************************************************************/ +/* These values control the behavior of net_timeval2desc */ + +enum tv2ds_remainder_e +{ + TV2DS_TRUNC = 0, /* Truncate microsecond remainder */ + TV2DS_ROUND, /* Round to the nearest full decisecond */ + TV2DS_CEIL /* Force to next larger full decisecond */ +}; + /**************************************************************************** * Public Data ****************************************************************************/ @@ -128,7 +137,8 @@ unsigned int net_dsec2tick(int dsec); * save new timeout values. * * Parameters: - * tv The struct timeval to convert + * tv - The struct timeval to convert + * remainder - Determines how to handler the microsecond remainder * * Returned Value: * The converted value @@ -137,7 +147,8 @@ unsigned int net_dsec2tick(int dsec); * ****************************************************************************/ -unsigned int net_timeval2dsec(FAR struct timeval *tv); +unsigned int net_timeval2dsec(FAR struct timeval *tv, + enum tv2ds_remainder_e remainder); /**************************************************************************** * Function: net_ipv6_pref2mask