os/ossrv/genericopenlibs/posixrealtimeextensions/src/clock_funcs.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /*
     2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
     3 * All rights reserved.
     4 * This component and the accompanying materials are made available
     5 * under the terms of "Eclipse Public License v1.0"
     6 * which accompanies this distribution, and is available
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
     8 *
     9 * Initial Contributors:
    10 * Nokia Corporation - initial contribution.
    11 *
    12 * Contributors:
    13 *
    14 * Description:  This is a project specific source file for building the 
    15 *                clock related functions as part of librt library.
    16 *
    17 */
    18 
    19 
    20 #include <time.h>
    21 #include <errno.h>
    22 #include <pthread.h>
    23 #include <stdlib.h>
    24 #include <e32std.h>
    25 #include <sys/_timeval.h>
    26 #include <sys/types.h>
    27 
    28 #include "lposix.h"
    29 
    30 #define UNIX_BASE	TTime(MAKE_TINT64(0x00dcddb3,0x0f2f8000))    // 00:00, Jan 1st 1970
    31 
    32 #define BOUNDARY_CHECK(rqtp) ( (rqtp->tv_nsec != 0 && rqtp->tv_nsec < 1000) || \
    33 							   rqtp->tv_nsec >= 1000000000L )\
    34 
    35 extern "C" {
    36 
    37 //Returns the resolution (granularity) of a clock
    38 //This value is placed in a (non-NULL) *res
    39 EXPORT_C int clock_getres(clockid_t clock_id, struct timespec* res)
    40 {
    41 	int retval = -1;
    42 	//We expect the user of the library to give us a valid pointer	
    43 	if(res == NULL)
    44 		{
    45 		return 0; //no strict reactions please.
    46 		}
    47 			
    48 	switch (clock_id) 
    49 		{
    50 		case CLOCK_REALTIME:
    51 			//Since Symbian OS is not realtime,we simulate the same using
    52 			//the available wall clock whose resolution is upto microseconds
    53 			res->tv_sec = 0;
    54 			res->tv_nsec = 1000;
    55 			retval = 0;
    56 			break;
    57 		
    58 		default:
    59 			//For all other clocks that cannot be supported or invalid clockids,
    60 			//we set errno to not-supported
    61 			retval = -1;
    62 			errno = EINVAL;
    63 			break;
    64 		}
    65 		
    66 	return retval;
    67 }
    68 
    69 //Allow the calling process to retrieve the value used by a clock which 
    70 //is specified by clock_id
    71 EXPORT_C int clock_gettime (clockid_t clock_id, struct timespec *tp)
    72 {
    73 	int retval = -1;
    74 	TTime t;
    75 	TTimeIntervalSeconds iSeconds;
    76 	TInt err;
    77 	//We expect the user of the library to give us a valid pointer	
    78 	if(tp == NULL)
    79 		{
    80 		errno = EFAULT;
    81 		return retval;
    82 		}
    83 
    84 	switch(clock_id)
    85 		{
    86 		case CLOCK_REALTIME:
    87 			//Since Symbian OS is not realtime,we simulate the same using
    88 			//the available wall clock.We use TTime::HomeTime() call to get
    89 			//the wall clock time
    90 			t.HomeTime();
    91 			err = t.SecondsFrom(UNIX_BASE, iSeconds); //TODO check for the negative tests..
    92 			if (!err)
    93 				{
    94 				t-=iSeconds;//extracting seconds info into iSeconds 			
    95 				tp->tv_sec = iSeconds.Int();
    96 				tp->tv_nsec = t.Int64();
    97 				retval = 0;
    98 				}
    99 			break;
   100 		
   101 		default:
   102 			//For all other clocks that cannot be supported or invalid clockids,
   103 			//we set errno to invalid
   104 			retval = -1;
   105 			errno = EINVAL;
   106 			break;
   107 		}
   108 	return retval;
   109 }
   110 
   111 
   112 //The clock_settime allow the calling process to set the value used by a 
   113 //clock which is specified by  clock_id
   114 EXPORT_C int clock_settime (clockid_t clock_id, const struct timespec *tp)
   115 {
   116 	int retval = -1;
   117 	TTime t(MAKE_TINT64 (0x00dcddb3 ,0x0f2f8000)) ;  // 00:00, Jan 1st 1970
   118 	TInt err;
   119 	TInt64 microtime;
   120 	
   121 	if(tp == NULL)
   122 		{
   123 		errno = EFAULT;
   124 		return retval;
   125 		}
   126 			
   127 	//Check for boundary values of seconds and microseconds
   128 	if (BOUNDARY_CHECK(tp))
   129 		{
   130 		errno = EINVAL;
   131 		return retval;
   132 		}
   133 
   134 	switch(clock_id)
   135 		{
   136 		case CLOCK_REALTIME:
   137 			//We support only the wall-clock,hence use the 
   138 			//User::SetHomeTime call to set the time
   139 			t+=(TTimeIntervalSeconds)tp->tv_sec;
   140 			microtime = (tp->tv_nsec)/1000;
   141 			t+=(TTimeIntervalMicroSeconds)microtime;        
   142 			err = User::SetUTCTime(t);
   143 			if(err)
   144 				{
   145 				MapError(err,errno);
   146 				break;
   147 				}
   148 			else
   149 				retval = 0;	
   150 			break;
   151 			
   152 		default:
   153 			//For all other clocks that cannot be supported or invalid clockids,
   154 			//we set errno to invalid
   155 			retval = -1;
   156 			errno = EINVAL;
   157 			break;
   158 		}	
   159 		
   160 	return retval;
   161 }
   162 
   163 
   164 //Returns the clock ID of the CPU-time clock of the process specified by pid
   165 EXPORT_C int clock_getcpuclockid (pid_t pid, clockid_t *clock_id)
   166 {
   167 	int retval = -1;
   168 
   169 	if(clock_id == NULL)
   170 		{
   171 		errno = EFAULT;
   172 		return retval;
   173 		}
   174 			
   175 	/* We don't allow any process ID but our own.  */
   176 	if (pid == 0)
   177 		{
   178 		//The only available clock is the realtime wall clock
   179 		//Hence we set the clockid to that
   180 		*clock_id = CLOCK_REALTIME;
   181 		retval = 0;
   182 		}
   183 	else
   184 		errno = ESRCH;
   185 	
   186 	return retval;
   187 }
   188 
   189 
   190 //clock_nanosleep will not be interrupted by the signal emulation. 
   191 //hence EINTR is not valid here. 
   192 
   193 EXPORT_C int clock_nanosleep(clockid_t clock_id, int flags,
   194        const struct timespec *rqtp, struct timespec */*rmtp*/)
   195 {
   196 	int retval = -1;
   197 	
   198 	if(rqtp == NULL)
   199 		{
   200 		errno = EFAULT;
   201 		return retval;
   202 		}
   203 			
   204 	//Check for boundary values of seconds and microseconds
   205 	if (BOUNDARY_CHECK(rqtp))
   206 		{
   207 		errno = EINVAL;
   208 		return retval;
   209 		}
   210 		
   211 	switch(clock_id)
   212 		{
   213 		case CLOCK_REALTIME:
   214 			{
   215 			switch(flags)
   216 				{
   217 				case TIMER_ABSTIME:
   218 					{
   219 					TTime lSetTime(MAKE_TINT64 (0x00dcddb3 ,0x0f2f8000)) ;  // 00:00, Jan 1st 1970				
   220 						
   221 					lSetTime+=(TTimeIntervalSeconds)rqtp->tv_sec;
   222 					lSetTime+=(TTimeIntervalMicroSeconds)(rqtp->tv_nsec/1000);
   223 						
   224 					User::At(lSetTime);
   225 					}
   226 					break;
   227 				
   228 				default:
   229 					{
   230 					unsigned long timeout;
   231 					timeout = (1000000 * rqtp->tv_sec) + (rqtp->tv_nsec /1000);
   232 					User::AfterHighRes(timeout);
   233 					}
   234 					break;
   235 				}
   236 			}
   237 			retval = 0;
   238 			break;
   239 				
   240 		default:
   241 			//For all other clocks that cannot be supported or invalid clockids,
   242 			//we set errno to invalid
   243 			retval = -1;
   244 			errno = EINVAL;
   245 			break;
   246 		}
   247 		
   248 	return retval;	
   249 }
   250 } // extern "C"
   251 
   252 //EOF
   253 
   254 
   255