diff -r 4816d766a08a -r f345bda72bc4 Symbian3/PDK/Source/GUID-6590B534-D976-5305-BE95-48DD05120DFB.dita --- a/Symbian3/PDK/Source/GUID-6590B534-D976-5305-BE95-48DD05120DFB.dita Tue Mar 30 11:42:04 2010 +0100 +++ b/Symbian3/PDK/Source/GUID-6590B534-D976-5305-BE95-48DD05120DFB.dita Tue Mar 30 11:56:28 2010 +0100 @@ -1,679 +1,679 @@ - - - - - -Miscellaneous -Topics - -
Poll using -select

The select() function call provides functionality -to scan descriptors for a ready event. The select() call -requires the system to scan through a bit mask of a file descriptor set against -its list of open descriptors to check for ready events, only stopping when -it reaches a maximum descriptor value. For a system with a relatively small -number of open descriptors this is quite efficient but for a large amount -of descriptors can be overly burdensome.

The Symbian P.I.P.S. libraries -are not expected to be dealing with a very large number of file descriptors -and so select() should be satisfactory for any applications -on a phone.

Note: P.I.P.S. does not support the poll() function.

Monitoring two pipes using -select()

The following code segment shows the usage of the select() function:

Int main(int argc, char **argv) -{ - FILE* ChildProcessStream1; - FILE* ChildProcessStream2; - int ChildProcessFD1; - int ChildProcessFD2; - fd_set SelectFDs; - int MaxFD; - struct timeval timeout; - int Ret; - - //Create child process 1 using popen(). - ChildProcessStream1 = popen("/root/PortDoc/Example7_c/Symbian/Child/ChildProg", "r"); - if(ChildProcessStream1 == NULL) - { - printf("\n Failure to create child process 1 with popen()\n"); - return EXIT_FAILURE; - } - - //Create child process 2 using popen(). - ChildProcessStream2 = popen("/root/PortDoc/Example7_c/Symbian/Child/ChildProg", "r"); - if(ChildProcessStream2 == NULL) - { - printf("\n Failure to create child process 2 with popen()\n"); - return EXIT_FAILURE; - } - - //Convert streams to file descriptors - ChildProcessFD1 = fileno(ChildProcessStream1); - ChildProcessFD2 = fileno(ChildProcessStream2); - - //Setup the select set - FD_ZERO(&SelectFDs); - FD_SET(ChildProcessFD1, &SelectFDs); - MaxFD = ChildProcessFD1; - FD_SET(ChildProcessFD2, &SelectFDs); - - //Calculate the largest Descriptor - if (ChildProcessFD2 > MaxFD) - MaxFD = ChildProcessFD2; - - //Setup a time out value in case neither return in a sufficient time - timeout.tv_sec = 3; - timeout.tv_usec = 0; - - //Issue select request - Ret = select(MaxFD + 1, &SelectFDs, NULL, NULL, &timeout); - if (Ret == -1) - { - //Error occurred - printf("\nCould not poll, error=%d",errno); - return EXIT_FAILURE; - } - else if (Ret == 0) - { - //Timed out - printf("\nTimed Out"); - } - else - { - //Create a receive buffer, and zero contents before receiving. - Char RxBuffer[100]; - memset(RxBuffer,0,sizeof(RxBuffer)); - - if (FD_ISSET(ChildProcessFD1, &SelectFDs)) - { - //Wait for data from child process 1. Child sends a string. - Int nbytes = read(ChildProcessFD1,RxBuffer,sizeof(RxBuffer)); - printf("\nMessage Received from Child1 First =%s",RxBuffer); - } - else if (FD_ISSET(ChildProcessFD2, &SelectFDs)) - { - //Wait for data from child process 2. Child sends a string. - Int nbytes = read(ChildProcessFD2,RxBuffer,sizeof(RxBuffer)); - printf("\nMessage Received from Child2 First =%s",RxBuffer); - } - } - - //Wait for Child Process to complete - pclose(ChildProcessStream1); - pclose(ChildProcessStream2); - - return EXIT_SUCCESS; -}
-
Socket IOCtl -options

The underlying implementation of sockets on the Symbian -platform imposes some restrictions on the socket options available in P.I.P.S. -and has also resulted in some new non-standard options to be created.

The -introduction of multi-homing (single link, multiple IP addresses) on Symbian -phones and the various methods of connecting to networks, such as Wi-Fi and -3G, with their varying degrees of cost to the user have made it important -to be able to choose which interface or access point is used to route socket -traffic. The Symbian RConnection class provides this functionality, -and is exposed in P.I.P.S. using some extra IOCtl options.

The list -of socket options available in P.I.P.S. are as follows:

- - - -

Socket Option

-

New

-

Description

-
- -

SIOCADDRT

-

Yes

-

Adds an entry to the interface routing table using the parameters -in the rtentry structure.

-
- -

SIOCATMARK

-

No

-

Determines whether the read pointer is currently pointing to the -logical mark in the data stream, testing whether the next read will be Out-of-Band -data or not.

-
- -

SIOCDELRT

-

Yes

-

Deletes an entry from the interface routing table using the parameters -in the rtentry structure.

-
- -

SIOCGIFACTIVECONF

-

Yes

-

Gets a list of interfaces/access points started by P.I.P.S. in an ifconf structure.

-
- -

SIOCGIFADDR

-

Yes

-

Gets the interface address. This is valid only for sockets with -address family AF_INET.

-
- -

SIOCGIFCONF

-

No

-

Gets a list of available interfaces/access points in an ifconf structure.

-
- -

SIOCGIFHWADDR

-

Yes

-

Gets the interface hardware address in an ifreq structure.

-
- -

SIOCGIFINDEX

-

Yes

-

Sets the index of an interface/access point from a name in an ifreq structure.

-
- -

SIOCGIFNUM

-

Yes

-

Return the total number of IP interfaces configured in the system.

-
- -

SIOCIFACTIVESTART

-

Yes

-

Attempts to start a sub-connection on an available interface/access -point using the parameters in an ifreq structure.

-
- -

SIOCIFSTART

-

Yes

-

Attempts to start an interface/access point using the parameters -in an ifreq structure.

-
- -

SIOCIFSTOP

-

Yes

-

Stops a previously started interface or sub-connection.

-
- -

SIOCSIFNAME

-

No

-

Sets the desired interface/access point name to start in an ifreq structure.

-
- - -

The follow code for a function shows how to start an interface -called "3G Access Point" and return the created socket.

int opensocket() -{ - int Sock; - struct ifreq Ifr; - char AccessPoint[]="3G Access Point"; - - //Open the socket - Sock = socket(AF_INET, SOCK_STREAM, 0); - if (Sock < 0) - { - printf("\nCannot open socket, error=%d",errno); - return -1; - } - - //Set up the interface request structure - bzero(&Ifr, sizeof(Ifr)); - strcpy(Ifr.ifr_name, AccessPoint); - - //Set the requested interface name - if (ioctl(Sock, SIOCSIFNAME, &Ifr)) - { - printf("\nCannot set the interface name, error=%d",errno); - close(Sock); - return -1; - } - - //Start the interface - if (ioctl(Sock, SIOCIFSTART, &Ifr)) - { - printf("\nCannot start the interface, error=%d",errno); - close(Sock); - return -1; - } - - //Return the opened socket - return Sock; -}
-
Mathematical -functions

The Symbian platform does not have any support for long -doubles so any P.I.P.S. programs which call long double versions of APIs will -actually invoke the double version of the API.

The Symbian platform -supports the use of a hardware floating point co-processor, however not all -phones incorporate an FPU (Floating Point Unit) and rely on software emulation -of floating point operations. Phones and computers equipped with an FPU provide -faster and more accurate floating point operations.

The Symbian platform -does not support complex numbers so the P.I.P.S. libraries are not able to -offer the POSIX complex number APIs.

Note: The mathematical -functions are included in the libm.dll file.

-
Error handling -and cleanup

It is important that the Symbian platform error codes -do not reach any ported application code. P.I.P.S. logically maps the native -OS error codes with the corresponding POSIX errno values -as per the standard. So, ported programs will not usually have to alter their -error checking/handling.

Mapping -P.I.P.S. error codes to the Symbian platform error codes

Porting -your application to the Symbian platform requires 'translating' the Symbian -platform error codes to POSIX error codes. User::Leaves() from -native Symbian APIs are trapped in P.I.P.S.. Calls to P.I.P.S. APIs from user -code need not be wrapped in TRAP s.

Occasionally -errors may be generated by the underlying Symbian platform that cannot be -translated to POSIX error codes, in which case the error variable errno will -be out of the usual range of values, above the maximum value of __EMAXERRNO or 124.

The -Symbian platform error code can be calculated using the following formula:

Symbian Error Code = -(errno - __EMAXERRNO)

Error -codes are defined in the errno.h file.

-
System logger

P.I.P.S. -does not supply a system logger for use with openlog(), syslog() and closelog(). -Instead, a rudimentary selection of functions which log to a file can be written -as demonstrated by the following example.

//define maximum length of identifier -#define SysLogMax 80 - -//logging file and identifier -FILE* fSysLog = NULL; -char fSysLogIdent[SysLogMax]; - -//close the log file -void my_closelog() -{ - //close the log file if it is open - if (fSysLog) - { - fclose(fSysLog); - fSysLog = NULL; - } - fSysLogIdent[0] = '\0'; -} - -//open a new log file -int my_openlog(const char *ident) -{ - //close the log file if it is open - if (fSysLog) - my_closelog(); - - //make the logging directory - mkdir("/syslog/", S_IWUSR | S_IRUSR | S_IXUSR); - - //open a new log file - fSysLog = fopen("/syslog/syslog.log", "a"); - - //return if the log file did not open - if (!fSysLog) - return -1; - - //set the identifier - if (!ident) - fSysLogIdent[0] = '\0'; - else - strncpy(fSysLogIdent, ident, SysLogMax); - - return 0; -} - -//output a string to the log file with a variable argument list -void my_vsyslog(const char *format, va_list formatlist) -{ - //open a log file if one does not exist - if (!fSysLog) - { - my_openlog(NULL); - } - - //check if there is a log file - if (fSysLog) - { - //print out the logging identifier if one exists - if (strlen(fSysLogIdent)) - { - fprintf(fSysLog, "%s ", fSysLogIdent); - } - - //print out the logging string - vfprintf(fSysLog, format, formatlist); - fprintf(fSysLog, "\r\n"); - } -} - -//output a string to the log file -void my_syslog(const char *format, ...) -{ - //create the variable argument list - va_list formatlist; - va_start(formatlist, format); - my_vsyslog(format, formatlist); - va_end(formatlist); -} - - -int main(int argc, char **argv) -{ - //open the log file - my_openlog("test"); - - //log a line - my_syslog("testing logging of the error number : %d", errno); - - //close the log - my_closelog(); - - return EXIT_SUCCESS; -}
-
Pthread barriers, -rwlocks and spinlocks

At present P.I.P.S. does not provide Pthread -barriers, rwlocks or spinlocks, but there are techniques which can be used -to implement the functionality using semaphores, mutexes and conditional variables.

The -following code sample (originally taken from http://heather.cs.ucdavis.edu/matloff/public_html/158/PLN/ParProcIntro.pdf) -demonstrates an implementation of a simple Pthread barrier.

struct barrier_t -{ - //number of nodes to synchronise - int nodes; - //two counts to avoid race conditions - int count[2]; - //which count to use - int whichcount; - //mutex to lock - pthread_mutex_t lock; - //condition to lock - pthread_cond_t cv; -}; - -//initialize a barrier -void InitBarrier(struct barrier_t* PB, int nodes) -{ - PB->nodes = nodes; - PB->count[0] = 0; - PB->count[1] = 0; - PB->whichcount = 0; - pthread_mutex_init(&PB->lock, NULL); - pthread_cond_init(&PB->cv, NULL); -} - -//destroy a barrier -void DestroyBarrier(struct barrier_t* PB) -{ - pthread_mutex_destroy(&PB->lock); - pthread_cond_destroy(&PB->cv); -} - -//wait for a barrier -void WaitBarrier(struct barrier_t* PB) -{ - int WhichCount, Count; - - //which counter variable to use - WhichCount = PB->whichcount; - - //lock the mutex - pthread_mutex_lock(&PB->lock); - - //get the count of nodes - Count = ++PB->count[WhichCount]; - - //test whether it should block - if (Count < PB->nodes) - pthread_cond_wait(&PB->cv, &PB->lock); - else - { - //reset the counter - PB->count[WhichCount] = 0; - PB->whichcount = 1 - WhichCount; - - //release the wait - pthread_cond_broadcast(&PB->cv); - } - - //unlock the threads - pthread_mutex_unlock(&PB->lock); -}

The following code was posted by Michael M. Lampkin as an -open source implementation of Pthread spin threads.

/********************************************************************** -BETA User Space spinlocks for POSIX systems lacking this functionality. -Copyright ©) 2003-2006 Michael M. Lampkin -Contact at michael.lampkin<at>ieee.org -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License version 2 as -published by the Free Software Foundation. -This program 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 General Public License for more details. -You should have received a copy of the GNU General Public License -version 2 along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 - -**********************************************************************/ - -#define _POSIX_C_SOURCE 200112L -#define _XOPEN_SOURCE 600 - -#define SPINLOCK_SPIN_MAX 50 - -/** - Need this "unique" value that we can use to take any spinlock - that has been initialized and identify attempts to call init - multiple times without corresponding calls to destroy. A hard - coded value should be fine though still a 1 in 4 billion chance - of collision with random data in un-inited spinlock. -**/ - -static long int spin_magic = 0x2FCD51F9L; - -/** - The spinlock structure which should NEVER be manipulated - by user code. - owner: - a pthread_t var indicating the current owner of the - spinlock or filled with 0's if not owned - mutex: - the primary mutex that any incoming threads will spin on - and attempt to obtain. - magic: - a field to hold a sentinel value indicating if the spinlock - is initialized. -**/ - -typedef struct -{ - pthread_t owner; - pthread_mutex_t mutex; - long int magic; -} -spinlock; - -/** - Function: spinlock_init - Description: - Initializes and allocates system resources to a - spinlock structure. - Parameters: - spin - a pointer to the spinlock structure to - be initialized. - pshared - either PTHREAD_PROCESS_PRIVATE or - PTHREAD_PROCESS_SHARED. If the system does not - support process shared mutexes or an unknown value - is given then defaults internally to a private type - with no error. -**/ - -int spinlock_init( spinlock * spin, int pshared ) -{ - int result; - pthread_mutexattr_t attr; - - /* If already inited... race condition with destroy */ - if ( NULL == spin ) - { - return EINVAL; - } - - if ( spin_magic == spin->magic ) - { - return EBUSY; - } - - ( void ) memset( & spin->owner, 0, sizeof( pthread_t ) ); - - /* Set our process sharing attribute - default to PRIVATE */ - result = pthread_mutexattr_init( & attr ); - - if ( 0 == result ) - { - if ( 0 < sysconf( _SC_THREAD_PROCESS_SHARED ) ) - { - if( PTHREAD_PROCESS_SHARED == pshared ) - { - result = pthread_mutexattr_setpshared( & attr, pshared ); - } - else - { - result = pthread_mutexattr_setpshared( & attr, PTHREAD_PROCESS_PRIVATE ); - } - } - } - - /* Need to add this to prevent recursive mutex default on some sys */ - if ( 0 == result ) - { - result = pthread_mutexattr_settype( & attr, PTHREAD_MUTEX_ERRORCHECK ); - } - - /* The following is a race against simultaneous calls to init */ - if ( 0 == result ) - { - result = pthread_mutex_init( & spin->mutex, & attr ); - } - - if ( 0 == result ) - { - spin->magic = spin_magic; - } - - ( void ) pthread_mutexattr_destroy( & attr ); - return result; -} - -/** - Function: spinlock_destroy - Description: - Releases system resources allocated to a spinlock - structure during initializion. - Parameters: - spin - a pointer to a previously initialized but - not destroyed spinlock. -**/ -int spinlock_destroy( spinlock * spin ) -{ - int result; - - if ( NULL == spin || spin_magic != spin->magic ) - { - return EINVAL; - } - - if ( 0 != ( result = pthread_mutex_destroy( & spin->mutex ) ) ) - { - return result; - } - - ( void ) memset( & spin->owner, 0, sizeof( pthread_t ) ); - - /** - A return of EINVAL on destroy means another thread is - also destroying. Ignore it. - **/ - spin->magic = 0; - - return 0; -} - -/** - Function: spinlock_lock - Description: - Attempts to acquire exclusive access to the specified - spinlock. If the spinlock is already owned then begin - spinning until ownership is obtained. - - Parameters: - spin - a pointer to an initialized spinlock. -**/ -int spinlock_lock( spinlock * spin ) -{ - pthread_t self; - int result; - int spin_count; - - if ( NULL == spin || spin_magic != spin->magic ) - { - return EINVAL; - } - - self = pthread_self( ); - if ( 0 == memcmp( & spin->owner, & self, sizeof( pthread_t ) ) ) - { - return EDEADLK; - } - - for ( ; 0 != ( result = pthread_mutex_trylock( & spin->mutex ) ) ; ) - { - if ( EBUSY == result ) - { - ++ spin_count; - - if ( SPINLOCK_SPIN_MAX == spin_count ) - { - ( void ) sched_yield( ); - spin_count = 0; - } - } - else - { - /* Destroy occurred on us... */ - return EINVAL; - } - } - - ( void ) memcpy( & spin->owner, & self, sizeof( pthread_t ) ); - return result; -} - -/**
-
Command line -shell

The Symbian platform phones do not have a command line shell -as standard. P.I.P.S. does however support the stdin(), stdout() and stderr() standard -streams, enabling parent processes to redirect a child's standard streams -for the exchange of data. Without explicitly redirecting the standard streams, -the default is for each to be redirected to the /dev/null directory. -The P.I.P.S. system() function does not create a shell -for a new program as in most POSIX implementations, however, it will start -a program and return the program's exit value.

-
User interfaces

Most -POSIX based systems interact with a windowing system such as X Windows and -libraries such as GTK. P.I.P.S., however, does not have its own UI libraries, -so any P.I.P.S. based applications that require UI functionality must rely -on the UI from the device manufacturer. As a consequence, for any UI program -that uses P.I.P.S., there must be an interaction between the Symbian platform -native C++ and P.I.P.S. C code.

-
One Definition -Rule - warning

Standard C++ states that the One Definition -Rule (ODR) must be maintained within a program.

The Symbian -platform can neither check (without significant modifications) that the ODR -is violated nor use the technique called symbol pre-emption to ensure that -the ODR is enforced.

Therefore, you must take care and must not assume -that there is only one copy of the symbol (that is, all instances of the same -symbol will have the same address) across all DLLs within a program.

+ + + + + +Miscellaneous +Topics +
    +
  • Poll using select

      +
    • Monitoring two pipes using select()

    • +
  • +
  • Socket IOCtl options

  • +
  • Mathematical functions

  • +
  • Error handling and cleanup

      +
    • Mapping P.I.P.S. error codes to the Symbian platform error codes

    • +
  • +
  • System logger

  • +
  • Pthread barriers, rwlocks and spinlocks

  • +
  • Command line shell

  • +
  • User interfaces

  • +
  • One Definition Rule - warning

  • +
+
Poll using +select

The select() function call provides functionality +to scan descriptors for a ready event. The select() call +requires the system to scan through a bit mask of a file descriptor set against +its list of open descriptors to check for ready events, only stopping when +it reaches a maximum descriptor value. For a system with a relatively small +number of open descriptors this is quite efficient but for a large amount +of descriptors can be overly burdensome.

The Symbian P.I.P.S. libraries +are not expected to be dealing with a very large number of file descriptors +and so select() should be satisfactory for any applications +on a phone.

Note: P.I.P.S. does not support the poll() function.

Monitoring two pipes using +select()

The following code segment shows the usage of the select() function:

Int main(int argc, char **argv) +{ + FILE* ChildProcessStream1; + FILE* ChildProcessStream2; + int ChildProcessFD1; + int ChildProcessFD2; + fd_set SelectFDs; + int MaxFD; + struct timeval timeout; + int Ret; + + //Create child process 1 using popen(). + ChildProcessStream1 = popen("/root/PortDoc/Example7_c/Symbian/Child/ChildProg", "r"); + if(ChildProcessStream1 == NULL) + { + printf("\n Failure to create child process 1 with popen()\n"); + return EXIT_FAILURE; + } + + //Create child process 2 using popen(). + ChildProcessStream2 = popen("/root/PortDoc/Example7_c/Symbian/Child/ChildProg", "r"); + if(ChildProcessStream2 == NULL) + { + printf("\n Failure to create child process 2 with popen()\n"); + return EXIT_FAILURE; + } + + //Convert streams to file descriptors + ChildProcessFD1 = fileno(ChildProcessStream1); + ChildProcessFD2 = fileno(ChildProcessStream2); + + //Setup the select set + FD_ZERO(&SelectFDs); + FD_SET(ChildProcessFD1, &SelectFDs); + MaxFD = ChildProcessFD1; + FD_SET(ChildProcessFD2, &SelectFDs); + + //Calculate the largest Descriptor + if (ChildProcessFD2 > MaxFD) + MaxFD = ChildProcessFD2; + + //Setup a time out value in case neither return in a sufficient time + timeout.tv_sec = 3; + timeout.tv_usec = 0; + + //Issue select request + Ret = select(MaxFD + 1, &SelectFDs, NULL, NULL, &timeout); + if (Ret == -1) + { + //Error occurred + printf("\nCould not poll, error=%d",errno); + return EXIT_FAILURE; + } + else if (Ret == 0) + { + //Timed out + printf("\nTimed Out"); + } + else + { + //Create a receive buffer, and zero contents before receiving. + Char RxBuffer[100]; + memset(RxBuffer,0,sizeof(RxBuffer)); + + if (FD_ISSET(ChildProcessFD1, &SelectFDs)) + { + //Wait for data from child process 1. Child sends a string. + Int nbytes = read(ChildProcessFD1,RxBuffer,sizeof(RxBuffer)); + printf("\nMessage Received from Child1 First =%s",RxBuffer); + } + else if (FD_ISSET(ChildProcessFD2, &SelectFDs)) + { + //Wait for data from child process 2. Child sends a string. + Int nbytes = read(ChildProcessFD2,RxBuffer,sizeof(RxBuffer)); + printf("\nMessage Received from Child2 First =%s",RxBuffer); + } + } + + //Wait for Child Process to complete + pclose(ChildProcessStream1); + pclose(ChildProcessStream2); + + return EXIT_SUCCESS; +}
+
Socket IOCtl +options

The underlying implementation of sockets on the Symbian +platform imposes some restrictions on the socket options available in P.I.P.S. +and has also resulted in some new non-standard options to be created.

The +introduction of multi-homing (single link, multiple IP addresses) on Symbian +phones and the various methods of connecting to networks, such as Wi-Fi and +3G, with their varying degrees of cost to the user have made it important +to be able to choose which interface or access point is used to route socket +traffic. The Symbian RConnection class provides this functionality, +and is exposed in P.I.P.S. using some extra IOCtl options.

The list +of socket options available in P.I.P.S. are as follows:

+ + + +

Socket Option

+

New

+

Description

+
+ +

SIOCADDRT

+

Yes

+

Adds an entry to the interface routing table using the parameters +in the rtentry structure.

+
+ +

SIOCATMARK

+

No

+

Determines whether the read pointer is currently pointing to the +logical mark in the data stream, testing whether the next read will be Out-of-Band +data or not.

+
+ +

SIOCDELRT

+

Yes

+

Deletes an entry from the interface routing table using the parameters +in the rtentry structure.

+
+ +

SIOCGIFACTIVECONF

+

Yes

+

Gets a list of interfaces/access points started by P.I.P.S. in an ifconf structure.

+
+ +

SIOCGIFADDR

+

Yes

+

Gets the interface address. This is valid only for sockets with +address family AF_INET.

+
+ +

SIOCGIFCONF

+

No

+

Gets a list of available interfaces/access points in an ifconf structure.

+
+ +

SIOCGIFHWADDR

+

Yes

+

Gets the interface hardware address in an ifreq structure.

+
+ +

SIOCGIFINDEX

+

Yes

+

Sets the index of an interface/access point from a name in an ifreq structure.

+
+ +

SIOCGIFNUM

+

Yes

+

Return the total number of IP interfaces configured in the system.

+
+ +

SIOCIFACTIVESTART

+

Yes

+

Attempts to start a sub-connection on an available interface/access +point using the parameters in an ifreq structure.

+
+ +

SIOCIFSTART

+

Yes

+

Attempts to start an interface/access point using the parameters +in an ifreq structure.

+
+ +

SIOCIFSTOP

+

Yes

+

Stops a previously started interface or sub-connection.

+
+ +

SIOCSIFNAME

+

No

+

Sets the desired interface/access point name to start in an ifreq structure.

+
+ + +

The follow code for a function shows how to start an interface +called "3G Access Point" and return the created socket.

int opensocket() +{ + int Sock; + struct ifreq Ifr; + char AccessPoint[]="3G Access Point"; + + //Open the socket + Sock = socket(AF_INET, SOCK_STREAM, 0); + if (Sock < 0) + { + printf("\nCannot open socket, error=%d",errno); + return -1; + } + + //Set up the interface request structure + bzero(&Ifr, sizeof(Ifr)); + strcpy(Ifr.ifr_name, AccessPoint); + + //Set the requested interface name + if (ioctl(Sock, SIOCSIFNAME, &Ifr)) + { + printf("\nCannot set the interface name, error=%d",errno); + close(Sock); + return -1; + } + + //Start the interface + if (ioctl(Sock, SIOCIFSTART, &Ifr)) + { + printf("\nCannot start the interface, error=%d",errno); + close(Sock); + return -1; + } + + //Return the opened socket + return Sock; +}
+
Mathematical +functions

The Symbian platform does not have any support for long +doubles so any P.I.P.S. programs which call long double versions of APIs will +actually invoke the double version of the API.

The Symbian platform +supports the use of a hardware floating point co-processor, however not all +phones incorporate an FPU (Floating Point Unit) and rely on software emulation +of floating point operations. Phones and computers equipped with an FPU provide +faster and more accurate floating point operations.

The Symbian platform +does not support complex numbers so the P.I.P.S. libraries are not able to +offer the POSIX complex number APIs.

Note: The mathematical +functions are included in the libm.dll file.

+
Error handling +and cleanup

It is important that the Symbian platform error codes +do not reach any ported application code. P.I.P.S. logically maps the native +OS error codes with the corresponding POSIX errno values +as per the standard. So, ported programs will not usually have to alter their +error checking/handling.

Mapping +P.I.P.S. error codes to the Symbian platform error codes

Porting +your application to the Symbian platform requires 'translating' the Symbian +platform error codes to POSIX error codes. User::Leaves() from +native Symbian APIs are trapped in P.I.P.S.. Calls to P.I.P.S. APIs from user +code need not be wrapped in TRAP s.

Occasionally +errors may be generated by the underlying Symbian platform that cannot be +translated to POSIX error codes, in which case the error variable errno will +be out of the usual range of values, above the maximum value of __EMAXERRNO or 124.

The +Symbian platform error code can be calculated using the following formula:

Symbian Error Code = -(errno - __EMAXERRNO)

Error +codes are defined in the errno.h file.

+
System logger

P.I.P.S. +does not supply a system logger for use with openlog(), syslog() and closelog(). +Instead, a rudimentary selection of functions which log to a file can be written +as demonstrated by the following example.

//define maximum length of identifier +#define SysLogMax 80 + +//logging file and identifier +FILE* fSysLog = NULL; +char fSysLogIdent[SysLogMax]; + +//close the log file +void my_closelog() +{ + //close the log file if it is open + if (fSysLog) + { + fclose(fSysLog); + fSysLog = NULL; + } + fSysLogIdent[0] = '\0'; +} + +//open a new log file +int my_openlog(const char *ident) +{ + //close the log file if it is open + if (fSysLog) + my_closelog(); + + //make the logging directory + mkdir("/syslog/", S_IWUSR | S_IRUSR | S_IXUSR); + + //open a new log file + fSysLog = fopen("/syslog/syslog.log", "a"); + + //return if the log file did not open + if (!fSysLog) + return -1; + + //set the identifier + if (!ident) + fSysLogIdent[0] = '\0'; + else + strncpy(fSysLogIdent, ident, SysLogMax); + + return 0; +} + +//output a string to the log file with a variable argument list +void my_vsyslog(const char *format, va_list formatlist) +{ + //open a log file if one does not exist + if (!fSysLog) + { + my_openlog(NULL); + } + + //check if there is a log file + if (fSysLog) + { + //print out the logging identifier if one exists + if (strlen(fSysLogIdent)) + { + fprintf(fSysLog, "%s ", fSysLogIdent); + } + + //print out the logging string + vfprintf(fSysLog, format, formatlist); + fprintf(fSysLog, "\r\n"); + } +} + +//output a string to the log file +void my_syslog(const char *format, ...) +{ + //create the variable argument list + va_list formatlist; + va_start(formatlist, format); + my_vsyslog(format, formatlist); + va_end(formatlist); +} + + +int main(int argc, char **argv) +{ + //open the log file + my_openlog("test"); + + //log a line + my_syslog("testing logging of the error number : %d", errno); + + //close the log + my_closelog(); + + return EXIT_SUCCESS; +}
+
Pthread barriers, +rwlocks and spinlocks

At present P.I.P.S. does not provide Pthread +barriers, rwlocks or spinlocks, but there are techniques which can be used +to implement the functionality using semaphores, mutexes and conditional variables.

The +following code sample (originally taken from http://heather.cs.ucdavis.edu/matloff/public_html/158/PLN/ParProcIntro.pdf) +demonstrates an implementation of a simple Pthread barrier.

struct barrier_t +{ + //number of nodes to synchronise + int nodes; + //two counts to avoid race conditions + int count[2]; + //which count to use + int whichcount; + //mutex to lock + pthread_mutex_t lock; + //condition to lock + pthread_cond_t cv; +}; + +//initialize a barrier +void InitBarrier(struct barrier_t* PB, int nodes) +{ + PB->nodes = nodes; + PB->count[0] = 0; + PB->count[1] = 0; + PB->whichcount = 0; + pthread_mutex_init(&PB->lock, NULL); + pthread_cond_init(&PB->cv, NULL); +} + +//destroy a barrier +void DestroyBarrier(struct barrier_t* PB) +{ + pthread_mutex_destroy(&PB->lock); + pthread_cond_destroy(&PB->cv); +} + +//wait for a barrier +void WaitBarrier(struct barrier_t* PB) +{ + int WhichCount, Count; + + //which counter variable to use + WhichCount = PB->whichcount; + + //lock the mutex + pthread_mutex_lock(&PB->lock); + + //get the count of nodes + Count = ++PB->count[WhichCount]; + + //test whether it should block + if (Count < PB->nodes) + pthread_cond_wait(&PB->cv, &PB->lock); + else + { + //reset the counter + PB->count[WhichCount] = 0; + PB->whichcount = 1 - WhichCount; + + //release the wait + pthread_cond_broadcast(&PB->cv); + } + + //unlock the threads + pthread_mutex_unlock(&PB->lock); +}

The following code was posted by Michael M. Lampkin as an +open source implementation of Pthread spin threads.

/********************************************************************** +BETA User Space spinlocks for POSIX systems lacking this functionality. +Copyright ©) 2003-2006 Michael M. Lampkin +Contact at michael.lampkin<at>ieee.org +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License version 2 as +published by the Free Software Foundation. +This program 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 General Public License for more details. +You should have received a copy of the GNU General Public License +version 2 along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + +**********************************************************************/ + +#define _POSIX_C_SOURCE 200112L +#define _XOPEN_SOURCE 600 + +#define SPINLOCK_SPIN_MAX 50 + +/** + Need this "unique" value that we can use to take any spinlock + that has been initialized and identify attempts to call init + multiple times without corresponding calls to destroy. A hard + coded value should be fine though still a 1 in 4 billion chance + of collision with random data in un-inited spinlock. +**/ + +static long int spin_magic = 0x2FCD51F9L; + +/** + The spinlock structure which should NEVER be manipulated + by user code. + owner: + a pthread_t var indicating the current owner of the + spinlock or filled with 0's if not owned + mutex: + the primary mutex that any incoming threads will spin on + and attempt to obtain. + magic: + a field to hold a sentinel value indicating if the spinlock + is initialized. +**/ + +typedef struct +{ + pthread_t owner; + pthread_mutex_t mutex; + long int magic; +} +spinlock; + +/** + Function: spinlock_init + Description: + Initializes and allocates system resources to a + spinlock structure. + Parameters: + spin - a pointer to the spinlock structure to + be initialized. + pshared - either PTHREAD_PROCESS_PRIVATE or + PTHREAD_PROCESS_SHARED. If the system does not + support process shared mutexes or an unknown value + is given then defaults internally to a private type + with no error. +**/ + +int spinlock_init( spinlock * spin, int pshared ) +{ + int result; + pthread_mutexattr_t attr; + + /* If already inited... race condition with destroy */ + if ( NULL == spin ) + { + return EINVAL; + } + + if ( spin_magic == spin->magic ) + { + return EBUSY; + } + + ( void ) memset( & spin->owner, 0, sizeof( pthread_t ) ); + + /* Set our process sharing attribute - default to PRIVATE */ + result = pthread_mutexattr_init( & attr ); + + if ( 0 == result ) + { + if ( 0 < sysconf( _SC_THREAD_PROCESS_SHARED ) ) + { + if( PTHREAD_PROCESS_SHARED == pshared ) + { + result = pthread_mutexattr_setpshared( & attr, pshared ); + } + else + { + result = pthread_mutexattr_setpshared( & attr, PTHREAD_PROCESS_PRIVATE ); + } + } + } + + /* Need to add this to prevent recursive mutex default on some sys */ + if ( 0 == result ) + { + result = pthread_mutexattr_settype( & attr, PTHREAD_MUTEX_ERRORCHECK ); + } + + /* The following is a race against simultaneous calls to init */ + if ( 0 == result ) + { + result = pthread_mutex_init( & spin->mutex, & attr ); + } + + if ( 0 == result ) + { + spin->magic = spin_magic; + } + + ( void ) pthread_mutexattr_destroy( & attr ); + return result; +} + +/** + Function: spinlock_destroy + Description: + Releases system resources allocated to a spinlock + structure during initializion. + Parameters: + spin - a pointer to a previously initialized but + not destroyed spinlock. +**/ +int spinlock_destroy( spinlock * spin ) +{ + int result; + + if ( NULL == spin || spin_magic != spin->magic ) + { + return EINVAL; + } + + if ( 0 != ( result = pthread_mutex_destroy( & spin->mutex ) ) ) + { + return result; + } + + ( void ) memset( & spin->owner, 0, sizeof( pthread_t ) ); + + /** + A return of EINVAL on destroy means another thread is + also destroying. Ignore it. + **/ + spin->magic = 0; + + return 0; +} + +/** + Function: spinlock_lock + Description: + Attempts to acquire exclusive access to the specified + spinlock. If the spinlock is already owned then begin + spinning until ownership is obtained. + + Parameters: + spin - a pointer to an initialized spinlock. +**/ +int spinlock_lock( spinlock * spin ) +{ + pthread_t self; + int result; + int spin_count; + + if ( NULL == spin || spin_magic != spin->magic ) + { + return EINVAL; + } + + self = pthread_self( ); + if ( 0 == memcmp( & spin->owner, & self, sizeof( pthread_t ) ) ) + { + return EDEADLK; + } + + for ( ; 0 != ( result = pthread_mutex_trylock( & spin->mutex ) ) ; ) + { + if ( EBUSY == result ) + { + ++ spin_count; + + if ( SPINLOCK_SPIN_MAX == spin_count ) + { + ( void ) sched_yield( ); + spin_count = 0; + } + } + else + { + /* Destroy occurred on us... */ + return EINVAL; + } + } + + ( void ) memcpy( & spin->owner, & self, sizeof( pthread_t ) ); + return result; +} + +/**
+
Command line +shell

The Symbian platform phones do not have a command line shell +as standard. P.I.P.S. does however support the stdin(), stdout() and stderr() standard +streams, enabling parent processes to redirect a child's standard streams +for the exchange of data. Without explicitly redirecting the standard streams, +the default is for each to be redirected to the /dev/null directory. +The P.I.P.S. system() function does not create a shell +for a new program as in most POSIX implementations, however, it will start +a program and return the program's exit value.

+
User interfaces

Most +POSIX based systems interact with a windowing system such as X Windows and +libraries such as GTK. P.I.P.S., however, does not have its own UI libraries, +so any P.I.P.S. based applications that require UI functionality must rely +on the UI from the device manufacturer. As a consequence, for any UI program +that uses P.I.P.S., there must be an interaction between the Symbian platform +native C++ and P.I.P.S. C code.

+
One Definition +Rule - warning

Standard C++ states that the One Definition +Rule (ODR) must be maintained within a program.

The Symbian +platform can neither check (without significant modifications) that the ODR +is violated nor use the technique called symbol pre-emption to ensure that +the ODR is enforced.

Therefore, you must take care and must not assume +that there is only one copy of the symbol (that is, all instances of the same +symbol will have the same address) across all DLLs within a program.

\ No newline at end of file