├── Message.h ├── .gitignore ├── SharedMemoryWrapper.h ├── Message.c ├── SerialWrapper.h ├── examples ├── SocketWrapperTest.c ├── SharedMemoryWrapperTest.c ├── SemaphoreWrapperTest.c ├── MessageQueueWrapperTest.c └── SerialWrapperTest.c ├── LICENSE ├── SocketWrapper.h ├── SharedMemoryWrapper.c ├── SemaphoreWrapper.h ├── README.md ├── Makefile ├── TimerWrapper.h ├── MessageQueueWrapper.h ├── SemaphoreWrapper.c ├── SocketWrapper.c ├── SerialWrapper.c ├── MessageQueueWrapper.c └── TimerWrapper.c /Message.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define MESSAGE_SIZE 64 6 | typedef struct Message { 7 | long mtype; 8 | char buffer[MESSAGE_SIZE]; 9 | int err; 10 | } Message; 11 | 12 | void clearMessage(Message* msg); 13 | void setMessage(Message* msg, char* buffer, int len, int mtype); 14 | const char* messageToString(Message* msg); 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | 31 | # Debug files 32 | *.dSYM/ 33 | -------------------------------------------------------------------------------- /SharedMemoryWrapper.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "errno.h" 5 | 6 | /* Create and delete shared memory: */ 7 | int sharedMemoryGet(key_t key, int size); 8 | int sharedMemoryCreate(key_t key, int size); 9 | int sharedMemoryCreateOrGet(key_t key, int size); 10 | int sharedMemoryCreateIfGone(key_t key, int size); 11 | int sharedMemoryDelete(int shmid); 12 | 13 | /* Attach / detach memory from process: */ 14 | void* sharedMemoryAttach(int shmid); 15 | int sharedMemoryDetatch(const void* shmaddr); 16 | 17 | /* Prevent shared memory from being swapped in / out: */ 18 | int sharedMemoryLock(int shmid); 19 | int sharedMemoryUnlock(int shmid); -------------------------------------------------------------------------------- /Message.c: -------------------------------------------------------------------------------- 1 | #include "Message.h" 2 | 3 | void clearMessage(Message* msg) 4 | { 5 | memset(msg->buffer, 0, sizeof(msg->buffer)); 6 | msg->err = 0; 7 | msg->mtype = 0; 8 | } 9 | 10 | void setMessage(Message* msg, char* buffer, int len, int mtype) 11 | { 12 | assert(len <= MESSAGE_SIZE); 13 | memcpy(msg->buffer, buffer, len); 14 | msg->err = 0; 15 | msg->mtype = mtype; 16 | } 17 | 18 | const char* messageToString(Message* msg) 19 | { 20 | static char toReturn[255]; 21 | memset(toReturn, 0, 255); 22 | 23 | sprintf(toReturn, "mtype: %ld\nerr: %d\nlen: %u\nbuffer: %s\n", 24 | msg->mtype, 25 | msg->err, 26 | sizeof(Message), 27 | msg->buffer); 28 | 29 | return toReturn; 30 | } 31 | -------------------------------------------------------------------------------- /SerialWrapper.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "TimerWrapper.h" 13 | 14 | #define HALF_SECOND 500000 15 | 16 | int serialOpen(char* port_address, int baud_rate); 17 | int serialFlush(int fd); 18 | int serialFlushRead(int fd); 19 | int serialFlushWrite(int fd); 20 | int serialWrite(int fd, char* data, int length); 21 | int serialRead(int fd, char* temp, int length); 22 | int serialCommandByDelim(int fd, char* cmd, char* reply, int replyLength, int usecs, char delim); 23 | int serialCommandByLength(int fd, char* cmd, char* reply, int replyLength, int usecs); 24 | int serialBufferCount(int fd); 25 | int serialClose(int fd); 26 | -------------------------------------------------------------------------------- /examples/SocketWrapperTest.c: -------------------------------------------------------------------------------- 1 | #include "SocketWrapper.h" 2 | 3 | int main() 4 | { 5 | char google[] = "173.194.79.103"; 6 | char message[] = "GET / HTTP/1.1\r\n\r\n"; 7 | char reply[2000]; 8 | int port = 80; 9 | int ret, sd; 10 | 11 | sd = socketCreate(); 12 | printf("Created socket wrapper with descriptor %d.\n", sd); 13 | 14 | ret = socketConnect(sd, google, port); 15 | printf("Socket wrapper connected to '%s' on port '%d' with return value %d.\n", google, port, ret); 16 | 17 | ret = socketSend(sd, message, -1); 18 | printf("Socket wrapper sent: \n\n'%s'\n\nto '%s' on port '%d' with return value %d.\n", message, google, port, ret); 19 | 20 | ret = socketReceive(sd, reply, 2000); 21 | printf("Socket wrapper received: \n\n'%s'\n\nfrom '%s' on port '%d' with return value %d.\n", reply, google, port, ret); 22 | 23 | ret = socketDisconnect(sd); 24 | printf("Socket wrapper disconnected from '%s' on port '%d' with return value %d.\n", google, port, ret); 25 | 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Kevin Dinkel 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | 21 | -------------------------------------------------------------------------------- /SocketWrapper.h: -------------------------------------------------------------------------------- 1 | #define __USE_GNU 2 | #define _GNU_SOURCE 3 | #include "errno.h" 4 | #include 5 | #include /* strlen */ 6 | #include /* sockets */ 7 | #include /* inet_addr */ 8 | #include /* write */ 9 | #include 10 | 11 | /* 12 | * SocketWrapper Class: 13 | * This class implements a connection based socket interface implementing 14 | * TCP/IP assuming IPv4 address types. 15 | * 16 | * 17 | */ 18 | int socketCreate(); 19 | int socketBind(int socket_desc, int port); 20 | int socketListen(int socket_desc, int max_num_clients); 21 | int socketAccept(int socket_desc); 22 | int socketConnect(int socket_desc, char* ip_address, int port); 23 | int socketDisconnect(int socket_desc); 24 | int socketPoll(int socket_desc, int usecs); 25 | int socketSend(int socket_desc, char* message, int length); 26 | int socketSend_nowait(int socket_desc, char* message, int length); 27 | int socketReceive(int socket_desc, char* server_reply, int length); 28 | int socketReceive_nowait(int socket_desc, char* server_reply, int length); 29 | int socketReceive_timeout(int socket_desc, char* server_reply, int length, int usecs); 30 | int getError(); 31 | -------------------------------------------------------------------------------- /examples/SharedMemoryWrapperTest.c: -------------------------------------------------------------------------------- 1 | #include "SharedMemoryWrapper.h" 2 | #include 3 | #include 4 | #include 5 | 6 | #define SHMEMSIZETEST 10 7 | #define TEST 6 8 | 9 | int main() 10 | { 11 | int ret, shmid; 12 | char* shmaddr = 0; 13 | char toWrite[3] = {'h','i','\0'}; 14 | unsigned int i; 15 | 16 | printf("Creating shared memory with key '%d' of size %d bytes.\n", TEST, SHMEMSIZETEST); 17 | shmid = sharedMemoryCreate(TEST, SHMEMSIZETEST); 18 | printf("Got shmid: %d\n\n", shmid); 19 | 20 | printf("Getting shared memory with key '%d' of size %d bytes.\n", TEST, SHMEMSIZETEST); 21 | shmid = sharedMemoryGet(TEST, SHMEMSIZETEST); 22 | printf("Got shmid: %d\n\n", shmid); 23 | 24 | printf("Attaching shared memory to address: %p\n", shmaddr); 25 | shmaddr = (char*) sharedMemoryAttach(shmid); 26 | printf("Which now points to: %p\n\n", shmaddr); 27 | 28 | printf("Locking shared memory...\n"); 29 | ret = sharedMemoryLock(shmid); 30 | printf("returned %d\n\n", ret); 31 | 32 | printf("Writing '%s' to shared memory...\n", toWrite); 33 | for(i = 0; i < strlen(toWrite); i++) 34 | *(shmaddr + i) = toWrite[i]; 35 | printf("Reading from shared memory: '%s'\n\n", shmaddr); 36 | 37 | printf("Unlocking shared memory...\n"); 38 | ret = sharedMemoryUnlock(shmid); 39 | printf("returned %d\n\n", ret); 40 | 41 | printf("Detatching shared memory from address: %p\n", shmaddr); 42 | ret = sharedMemoryDetatch(shmaddr); 43 | printf("returned %d\n", ret); 44 | printf("Which now points to: %p\n\n", shmaddr); 45 | 46 | printf("Deleting shared memory... \n"); 47 | ret = sharedMemoryDelete(shmid); 48 | printf("returned: %d\n", ret); 49 | 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /SharedMemoryWrapper.c: -------------------------------------------------------------------------------- 1 | #include "SharedMemoryWrapper.h" 2 | 3 | int sharedMemoryGet(key_t key, int size) 4 | { 5 | int shmid; 6 | 7 | if ((shmid = shmget(key, size, 0666)) == -1) 8 | return -1; 9 | 10 | return shmid; 11 | } 12 | 13 | int sharedMemoryCreate(key_t key, int size) 14 | { 15 | int shmid; 16 | 17 | if ((shmid = shmget(key, size, IPC_CREAT | 0666)) == -1) 18 | return -1; 19 | 20 | return shmid; 21 | } 22 | 23 | int sharedMemoryCreateOrGet(key_t key, int size) 24 | { 25 | int shmid; 26 | 27 | /* If memory has already been created.. then just get it: */ 28 | if ((shmid = shmget(key, size, IPC_CREAT | IPC_EXCL | 0666)) == -1) 29 | { 30 | if( errno != EEXIST ) 31 | return -1; 32 | 33 | if ((shmid = shmget(key, size, 0666)) == -1) 34 | return -1; 35 | } 36 | 37 | return shmid; 38 | } 39 | 40 | int sharedMemoryCreateIfGone(key_t key, int size) 41 | { 42 | int shmid; 43 | 44 | /* If memory has already been created.. then just get it: */ 45 | if ((shmid = shmget(key, size, IPC_CREAT | IPC_EXCL | 0666)) == -1) 46 | return errno; 47 | 48 | return shmid; 49 | } 50 | 51 | void* sharedMemoryAttach(int shmid) 52 | { 53 | return shmat(shmid, 0, 0); 54 | } 55 | 56 | int sharedMemoryDetatch(const void* shmaddr) 57 | { 58 | if( shmdt(shmaddr) == -1 ) 59 | return errno; 60 | 61 | return 0; 62 | } 63 | 64 | int sharedMemoryDelete(int shmid) 65 | { 66 | if( shmctl(shmid, IPC_RMID, 0) == -1 ) 67 | return errno; 68 | 69 | return 0; 70 | } 71 | 72 | int sharedMemoryLock(int shmid) 73 | { 74 | if( shmctl(shmid, SHM_LOCK, 0) == -1 ) 75 | return errno; 76 | 77 | return 0; 78 | } 79 | 80 | int sharedMemoryUnlock(int shmid) 81 | { 82 | if( shmctl(shmid, SHM_UNLOCK, 0) == -1 ) 83 | return errno; 84 | 85 | return 0; 86 | } -------------------------------------------------------------------------------- /SemaphoreWrapper.h: -------------------------------------------------------------------------------- 1 | /* for linux , semtimedop() declaration */ 2 | #define __USE_GNU 3 | #define _GNU_SOURCE 4 | #include 5 | #include 6 | #include 7 | 8 | union semun 9 | { 10 | int val; /* value for SETVAL */ 11 | struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */ 12 | ushort *array; /* array for GETALL, SETALL */ 13 | /* Linux specific part: */ 14 | struct seminfo *__buf; /* buffer for IPC_INFO */ 15 | }; 16 | 17 | /* Create num_of_sem semaphores assoc. with the path. */ 18 | /* Returns the semid */ 19 | int semCreate(key_t key, int num_of_sem); 20 | 21 | /* Returns the semaphore ID for the path specified */ 22 | int semGet(key_t key, int number_of_sem); 23 | 24 | /* Delete the semaphores associated with semid */ 25 | int semDelete(int semid); 26 | 27 | /* Sets semaphore_number assoc. with the semid to value */ 28 | int semSetValue(int semid, int semaphore_number, int value); 29 | 30 | /* Gets the semaphore value from semaphore_number assoc. with the semid */ 31 | int semGetValue(int semid, int semaphore_number); 32 | 33 | /* Increment semaphore value by one */ 34 | int semSignal(int semid, int semaphore_number); 35 | int semIncrement(int semid, int semaphore_number, int incrementBy); 36 | 37 | /* Decrement semaphore value by one */ 38 | int semWait(int semid, int semaphore_number); 39 | int semDecrement(int semid, int semaphore_number, int decrementBy); 40 | 41 | /* Increment semaphore value by one */ 42 | int semSignal_timeout(int semid, int semaphore_number, long usecs); 43 | int semIncrement_timeout(int semid, int semaphore_number, int incrementBy, long usecs); 44 | 45 | /* Decrement semaphore value by one */ 46 | int semWait_timeout(int semid, int semaphore_number, long usecs); 47 | int semDecrement_timeout(int semid, int semaphore_number, int decrementBy, long usecs); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # linux-ipc-wrappers 2 | This is a set of simple C libraries that simplify the use of Linux message queues, semaphores, shared memory, sockets, timers, and even serial ports. 3 | 4 | The wrappers provided include: 5 | 6 | * **MessageQueueWrapper.c** - a simple wrapper around System V message queues 7 | * **SemaphoreWrapper.c** - a simple wrapper around Linux semaphores 8 | * **SerialWrapper.c** - a simple wrapper which allows reading and writing from serial ports with all flow control turned off 9 | * **SharedMemoryWrapper.c** - a simple wrapper around Linux shared memory 10 | * **SocketWrapper.c** - a simple wrapper for performing IPv4 TCP socket operations 11 | * **TimerWrapper.c** - a simple wrapper around linux time operations, providing a one-shot timer, a periodic timer, and a stop watch like timer 12 | 13 | 14 | #### Compilation: 15 | Just run `make`. 16 | 17 | #### Examples: 18 | Examples on how to use these libraries can be found in the `examples/` directory. Compiling the source will create 4 examples programs: 19 | 20 | * `messageQueueWrapperTest` - This example creates a System V message queue that connects two message queue ids. A message is sent between the two ids. 21 | * `semaphoreWrapperTest` - This example creates a set of semaphores and performs various actions on them. 22 | * `socketWrapperTest` - This example sends an HTTP request to a server and returns the resultant HTML. 23 | * `serialWrapperTest` - This example requires the program `socat` which can be installed via `apt-get` or similiar. `socat` is used to connect a `/dev/pts/#` to `stdout` simulating a serial port connection. The example sends data through the simulated serial port and then receives data given by the user. 24 | 25 | #### Contribution: 26 | These wrappers mostly serve as a reminder to me of how to use the various Linux IPC functions. If you find a bug, or want to improve what I have here, please submit a pull request. 27 | 28 | Enjoy! 29 | -------------------------------------------------------------------------------- /examples/SemaphoreWrapperTest.c: -------------------------------------------------------------------------------- 1 | #include "SemaphoreWrapper.h" 2 | #include 3 | #include 4 | #include 5 | 6 | #define TEST_KEY 1 7 | #define NUMSEMSIZETEST 10 8 | #define SEMNUM 0 9 | #define VAL 5 10 | 11 | int main() 12 | { 13 | int ret, semid; 14 | 15 | printf("Creating %d semaphores with key %d\n", NUMSEMSIZETEST, TEST_KEY); 16 | semid = semCreate(TEST_KEY, NUMSEMSIZETEST); 17 | printf("Got semid: %d\n", semid); 18 | 19 | printf("Getting %d semaphores with key %d\n", NUMSEMSIZETEST, TEST_KEY); 20 | semid = semGet(TEST_KEY, NUMSEMSIZETEST); 21 | printf("Got semid: %d\n", semid); 22 | 23 | printf("Setting semaphore %d to %d\n", SEMNUM, VAL); 24 | ret = semSetValue(semid, SEMNUM, VAL); 25 | printf("returned: %d\n", ret); 26 | 27 | printf("Getting semaphore: %d\n", SEMNUM); 28 | ret = semGetValue(semid, SEMNUM); 29 | printf("returned: %d\n", ret); 30 | 31 | printf("Signaling semaphore %d with increment value of 2\n", SEMNUM); 32 | ret = semIncrement(semid, SEMNUM, 2); 33 | printf("returned: %d\n", ret); 34 | 35 | printf("Getting semaphore: %d\n", SEMNUM); 36 | ret = semGetValue(semid, SEMNUM); 37 | printf("returned: %d\n", ret); 38 | 39 | printf("Waiting on semaphore: %d\n", SEMNUM); 40 | ret = semWait(semid, SEMNUM); 41 | printf("returned: %d\n", ret); 42 | 43 | printf("Getting semaphore: %d\n", SEMNUM); 44 | ret = semGetValue(semid, SEMNUM); 45 | printf("returned: %d\n", ret); 46 | 47 | printf("Setting semaphore %d to %d\n", SEMNUM, 0); 48 | ret = semSetValue(semid, SEMNUM, 0); 49 | printf("returned: %d\n", ret); 50 | 51 | printf("Getting semaphore: %d\n", SEMNUM); 52 | ret = semGetValue(semid, SEMNUM); 53 | printf("returned: %d\n", ret); 54 | 55 | printf("Waiting on with timeout on locked semaphore: %d\n", SEMNUM); 56 | ret = semWait_timeout(semid, SEMNUM, 100000); 57 | printf("returned: %d (-1 means the semaphore timed out)\n", ret); 58 | 59 | printf("Deleting semaphores... \n"); 60 | ret = semDelete(semid); 61 | printf("returned: %d\n", ret); 62 | 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /examples/MessageQueueWrapperTest.c: -------------------------------------------------------------------------------- 1 | #include "MessageQueueWrapper.h" 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | int i; 9 | int key = 10; 10 | int key2 = key + 1; 11 | int qid, qid2; 12 | Message msg, msg2; 13 | char buffer[MESSAGE_SIZE]; 14 | int ret; 15 | int mtype=1; 16 | 17 | /* Fill buffers with data: */ 18 | memset(buffer, 0, MESSAGE_SIZE); 19 | for( i = 0; i < 26; i++ ){ 20 | buffer[i] = 65 + i; 21 | } 22 | 23 | /* Create message queues: */ 24 | printf("making msq queue with key %d\n", key); 25 | qid = messageQueueCreate(key); 26 | printf("message queue returned qid %d\n", qid); 27 | if(qid == -1){ return -1; } 28 | 29 | printf("making another msq queue with same key %d\n", key); 30 | qid = messageQueueCreate(key); 31 | printf("message queue returned qid %d\n", qid); 32 | if(qid == -1){ return -1; } 33 | 34 | printf("making second msq queue with key %d\n", key2); 35 | qid2 = messageQueueCreate(key2); 36 | printf("second message queue returned qid %d\n", qid2); 37 | if(qid2 == -1){ return -1; } 38 | 39 | /* Create messages: */ 40 | printf("creating message\n%s\n", messageToString(&msg)); 41 | clearMessage(&msg); 42 | printf("clearing message\n%s\n", messageToString(&msg)); 43 | clearMessage(&msg2); 44 | printf("creating second blank message\n%s\n", messageToString(&msg2)); 45 | 46 | setMessage(&msg, buffer, MESSAGE_SIZE, mtype); 47 | printf("Making message with buffer:\n%s\n\n", buffer); 48 | 49 | /* Send message: */ 50 | printf("Sending message from qid: %d to qid: %d\n", qid, qid2); 51 | ret = messageQueueSend(qid2, &msg); 52 | printf("Sending message returned %d\n", ret); 53 | printf("Sent message: %s\n", messageToString(&msg)); 54 | 55 | /* Receive message: */ 56 | printf("Receiving message from qid: %d\n", qid2); 57 | ret = messageQueueReceive(qid2, &msg2, mtype); 58 | printf("Receiving message returned %d\n", ret); 59 | printf("Received message: %s\n", messageToString(&msg2)); 60 | 61 | /* Delete queues: */ 62 | printf("Deleting qid: %d returned %d\n", qid , messageQueueDelete(qid)); 63 | printf("Deleting qid: %d returned %d\n", qid2, messageQueueDelete(qid2)); 64 | 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-O3 -pipe -Wall -Wextra -pedantic 3 | INCLUDE=-I. 4 | EXAMPLE_DIR=examples 5 | OBJ=Message.o TimerWrapper.o MessageQueueWrapper.o SemaphoreWrapper.o SerialWrapper.o SharedMemoryWrapper.o SocketWrapper.o $(EXAMPLE_DIR)/MessageQueueWrapperTest.o $(EXAMPLE_DIR)/SemaphoreWrapperTest.o $(EXAMPLE_DIR)/SerialWrapperTest.o $(EXAMPLE_DIR)/SharedMemoryWrapperTest.o $(EXAMPLE_DIR)/SocketWrapperTest.o 6 | BIN=$(EXAMPLE_DIR)/messageQueueWrapperTest $(EXAMPLE_DIR)/semaphoreWrapperTest $(EXAMPLE_DIR)/serialWrapperTest $(EXAMPLE_DIR)/sharedMemoryWrapperTest $(EXAMPLE_DIR)/socketWrapperTest 7 | 8 | all: $(OBJ) $(BIN) 9 | 10 | Message.o: Message.c 11 | $(CC) -o $@ $(CFLAGS) -c $^ 12 | 13 | TimerWrapper.o: TimerWrapper.c 14 | $(CC) -o $@ $(CFLAGS) -c $^ 15 | 16 | MessageQueueWrapper.o: MessageQueueWrapper.c 17 | $(CC) -o $@ $(CFLAGS) -c $^ 18 | 19 | SemaphoreWrapper.o: SemaphoreWrapper.c 20 | $(CC) -o $@ $(CFLAGS) -c $^ 21 | 22 | SharedMemoryWrapper.o: SharedMemoryWrapper.c 23 | $(CC) -o $@ $(CFLAGS) -c $^ 24 | 25 | SocketWrapper.o: SocketWrapper.c 26 | $(CC) -o $@ $(CFLAGS) -c $^ 27 | 28 | SerialWrapper.o: SerialWrapper.c 29 | $(CC) -o $@ $(CFLAGS) -c $^ 30 | 31 | $(EXAMPLE_DIR)/MessageQueueWrapperTest.o: $(EXAMPLE_DIR)/MessageQueueWrapperTest.c 32 | $(CC) -o $@ $(CFLAGS) -c $(INCLUDE) $^ 33 | 34 | $(EXAMPLE_DIR)/messageQueueWrapperTest: $(EXAMPLE_DIR)/messageQueueWrapperTest.o MessageQueueWrapper.o TimerWrapper.o Message.o 35 | $(CC) -o $@ $(CFLAGS) $^ -lrt 36 | 37 | $(EXAMPLE_DIR)/SemaphoreWrapperTest.o: $(EXAMPLE_DIR)/SemaphoreWrapperTest.c 38 | $(CC) -o $@ $(CFLAGS) -c $(INCLUDE) $^ 39 | 40 | $(EXAMPLE_DIR)/semaphoreWrapperTest: $(EXAMPLE_DIR)/semaphoreWrapperTest.o SemaphoreWrapper.o 41 | $(CC) -o $@ $(CFLAGS) $^ 42 | 43 | $(EXAMPLE_DIR)/SerialWrapperTest.o: $(EXAMPLE_DIR)/SerialWrapperTest.c 44 | $(CC) -o $@ $(CFLAGS) -c $(INCLUDE) $^ 45 | 46 | $(EXAMPLE_DIR)/serialWrapperTest: $(EXAMPLE_DIR)/SerialWrapperTest.o SerialWrapper.o TimerWrapper.o 47 | $(CC) -o $@ $(CFLAGS) $^ -lrt 48 | 49 | $(EXAMPLE_DIR)/SharedMemoryWrapperTest.o: $(EXAMPLE_DIR)/SharedMemoryWrapperTest.c 50 | $(CC) -o $@ $(CFLAGS) -c $(INCLUDE) $^ 51 | 52 | $(EXAMPLE_DIR)/sharedMemoryWrapperTest: $(EXAMPLE_DIR)/SharedMemoryWrapperTest.o SharedMemoryWrapper.o 53 | $(CC) -o $@ $(CFLAGS) $^ -lrt 54 | 55 | $(EXAMPLE_DIR)/SocketWrapperTest.o: $(EXAMPLE_DIR)/SocketWrapperTest.c 56 | $(CC) -o $@ $(CFLAGS) -c $(INCLUDE) $^ 57 | 58 | $(EXAMPLE_DIR)/socketWrapperTest: $(EXAMPLE_DIR)/SocketWrapperTest.o SocketWrapper.o 59 | $(CC) -o $@ $(CFLAGS) $^ -lrt 60 | 61 | clean: 62 | -rm -f $(OBJ) $(BIN) -------------------------------------------------------------------------------- /TimerWrapper.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* 6 | // A wrapper around the posix timer system. It implements 7 | // a downwards ticking one-shot timer that expires after the 8 | // specified time. 9 | */ 10 | typedef struct timer{ 11 | timer_t timerid; 12 | } timer; 13 | 14 | int timerCreate(timer* timerid); 15 | int timerDelete(timer* timerid); 16 | int timerSet(timer* timerid, const time_t sec, const long nsec); 17 | int timerSet_us(timer* timerid, const long usecs); 18 | int timerUnset(timer* timerid); 19 | int timerGet(timer* timerid, time_t* sec, long* nsec); 20 | int isTimerExpired(timer* timerid); 21 | 22 | /* 23 | // A wrapper around the posix timer system. It implements 24 | // a downwards ticking periodic timer that expires after the 25 | // specified time and calls a callback function. 26 | */ 27 | typedef struct periodicTimer{ 28 | timer_t timerid; 29 | int signum; 30 | sigset_t set; 31 | int enabled; 32 | } periodicTimer; 33 | 34 | int periodicTimerCreate(periodicTimer* pt, long threadId, int signalNum); 35 | int periodicTimerDelete(periodicTimer* pt); 36 | int periodicTimerSet(periodicTimer* pt, const time_t sec, const long nsec); 37 | int periodicTimerSet_us(periodicTimer* pt, const long usecs); 38 | int periodicTimerUnset(periodicTimer* pt); 39 | int periodicTimerGet(periodicTimer* pt, time_t* sec, long* nsec); 40 | int periodicTimerWait(periodicTimer* pt, long sec, long nsec); 41 | int periodicTimerIntervalGet(periodicTimer* pt, time_t* sec, long* nsec); 42 | void periodicTimerEnable(periodicTimer* pt); 43 | void periodicTimerDisable(periodicTimer* pt); 44 | int isPeriodicTimerSet(periodicTimer* pt); 45 | int isPeriodicTimerEnabled(periodicTimer* pt); 46 | 47 | /* 48 | // An upwards counting stopwatch-like timer that can be used 49 | // for timing system performance. 50 | */ 51 | typedef struct stopWatch{ 52 | struct timespec start_t; 53 | struct timespec stop_t; 54 | } stopWatch; 55 | 56 | int stopWatchStart(stopWatch* sw); 57 | int stopWatchStop(stopWatch* sw); 58 | long stopWatchReport(stopWatch* sw); 59 | 60 | /* The most accurate real-time sleeper: */ 61 | extern int rt_sleep(const time_t sec, const long nsec); 62 | extern int rt_sleep_us(const long usec); 63 | 64 | /* Most accurate way to get system time */ 65 | extern int rt_time( time_t* sec, long* nsec ); 66 | extern int rt_time_ts( struct timespec* systemTime ); 67 | unsigned long rt_time_ns(); 68 | unsigned long rt_time_nsts(struct timespec timeSpecStruct); 69 | 70 | /* Utility functions: */ 71 | extern void usec_2_sec_nsec(long usec, time_t* sec, long* nsec); -------------------------------------------------------------------------------- /MessageQueueWrapper.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "errno.h" 7 | #include 8 | #include "Message.h" 9 | #include "TimerWrapper.h" 10 | 11 | /***************************************************************** 12 | * Class: messageQueueWrapper 13 | * Purpose: This class contains functions to create and delete 14 | * message queues, as well as send and receive messages. 15 | * TODO: Consolidate this so that there is only one 16 | * implementation of messageQueueSend() and messageQueueReceive(). 17 | * Member messageQueueCreate(): Creates a message queue 18 | * Member messageQueueDelete(): Deletes a message queue 19 | * Member messageQueueSend() (3): Sends a message over a message queue. 20 | * Member messageQueueReceive() (3): Receives a message from a message queue. 21 | *****************************************************************/ 22 | 23 | /***************************************************************** 24 | * Example IPC Limits: 25 | * 26 | * >> ipcs -l 27 | * 28 | * ------ Shared Memory Limits -------- 29 | * max number of segments = 4096 // SHMMNI 30 | * max seg size (kbytes) = 32768 // SHMMAX 31 | * max total shared memory (kbytes) = 8388608 // SHMALL 32 | * min seg size (bytes) = 1 33 | * 34 | * ------ Semaphore Limits -------- 35 | * max number of arrays = 1024 // SEMMNI 36 | * max semaphores per array = 250 // SEMMSL 37 | * max semaphores system wide = 256000 // SEMMNS 38 | * max ops per semop call = 32 // SEMOPM 39 | * semaphore max value = 32767 40 | * 41 | * ------ Messages: Limits -------- 42 | * max queues system wide = 1024 // MSGMNI 43 | * max size of message (bytes) = 65536 // MSGMAX 44 | * default max size of queue (bytes) = 65536 // MSGMNB 45 | *****************************************************************/ 46 | 47 | /* Message queue utilities */ 48 | int messageQueueGet(key_t key); 49 | int messageQueueCreate(key_t key); 50 | int messageQueueDelete(int qid); 51 | 52 | /* Message send: */ 53 | int messageQueueSend(int qid, Message *msg); 54 | int messageQueueSend_nowait(int qid, Message *msg); 55 | int messageQueueSend_timeout(int qid, Message *msg, int usec); 56 | 57 | /* Message Receive */ 58 | int messageQueueReceive(int qid, Message *msg, long type); 59 | int messageQueueReceive_nowait(int qid, Message *msg, long type); 60 | int messageQueueReceive_timeout(int qid, Message *msg, int usec, long type); 61 | -------------------------------------------------------------------------------- /SemaphoreWrapper.c: -------------------------------------------------------------------------------- 1 | #include "SemaphoreWrapper.h" 2 | 3 | int semCreate(key_t key, int number_of_sem) 4 | { 5 | int semid; 6 | 7 | if( (semid = semget(key, number_of_sem, 0666 | IPC_CREAT)) == -1) 8 | return -1; 9 | 10 | return semid; 11 | } 12 | 13 | /* Returns the semaphore ID for the path specified */ 14 | int semGet(key_t key, int number_of_sem) 15 | { 16 | int semid; 17 | 18 | if( (semid = semget(key, number_of_sem, 0666)) == -1 ) 19 | return -1; 20 | 21 | return semid; 22 | } 23 | 24 | int semDelete(int semid) 25 | { 26 | union semun arg; 27 | 28 | return semctl(semid, 0, IPC_RMID, arg); 29 | } 30 | 31 | /* Sets semaphore_number assoc. with the semid to value */ 32 | int semSetValue(int semid, int semaphore_number, int value) 33 | { 34 | union semun arg; 35 | arg.val = value; 36 | 37 | return semctl(semid, semaphore_number, SETVAL, arg); 38 | } 39 | 40 | /* Gets the semaphore value from semaphore_number assoc. with the semid */ 41 | int semGetValue(int semid, int semaphore_number) 42 | { 43 | union semun arg; 44 | 45 | return semctl(semid, semaphore_number, GETVAL, arg); 46 | } 47 | 48 | /* Increment semaphore value by one */ 49 | int semSignal(int semid, int semaphore_number) 50 | { 51 | struct sembuf sops; 52 | sops.sem_num = semaphore_number; 53 | sops.sem_op = 1; 54 | sops.sem_flg = SEM_UNDO; 55 | return semop(semid, &sops, 1); 56 | } 57 | 58 | int semIncrement(int semid, int semaphore_number, int incrementBy) 59 | { 60 | struct sembuf sops; 61 | sops.sem_num = semaphore_number; 62 | sops.sem_op = incrementBy; 63 | sops.sem_flg = SEM_UNDO; 64 | return semop(semid, &sops, 1); 65 | } 66 | 67 | /* Decrement semaphore value by one */ 68 | int semWait(int semid, int semaphore_number) 69 | { 70 | struct sembuf sops; 71 | sops.sem_num = semaphore_number; 72 | sops.sem_op = -1; 73 | sops.sem_flg = SEM_UNDO; 74 | return semop(semid, &sops, 1); 75 | } 76 | 77 | int semDecrment(int semid, int semaphore_number, int decrementBy) 78 | { 79 | struct sembuf sops; 80 | sops.sem_num = semaphore_number; 81 | sops.sem_op = decrementBy; 82 | sops.sem_flg = SEM_UNDO; 83 | return semop(semid, &sops, 1); 84 | } 85 | 86 | /* Increment semaphore value by one */ 87 | int semSignal_timeout(int semid, int semaphore_number, long usecs) 88 | { 89 | struct sembuf sops; 90 | struct timespec timeout; 91 | 92 | sops.sem_num = semaphore_number; 93 | sops.sem_op = 1; 94 | sops.sem_flg = SEM_UNDO; 95 | 96 | timeout.tv_sec = 0; 97 | timeout.tv_nsec = usecs*1000; 98 | 99 | return semtimedop(semid, &sops, 1, &timeout); 100 | } 101 | 102 | int semIncrement_timeout(int semid, int semaphore_number, int incrementBy, long usecs) 103 | { 104 | struct sembuf sops; 105 | struct timespec timeout; 106 | 107 | sops.sem_num = semaphore_number; 108 | sops.sem_op = incrementBy; 109 | sops.sem_flg = SEM_UNDO; 110 | 111 | timeout.tv_sec = 0; 112 | timeout.tv_nsec = usecs*1000; 113 | 114 | return semtimedop(semid, &sops, 1, &timeout); 115 | } 116 | 117 | /* Decrement semaphore value by one */ 118 | int semWait_timeout(int semid, int semaphore_number, long usecs) 119 | { 120 | struct sembuf sops; 121 | struct timespec timeout; 122 | 123 | sops.sem_num = semaphore_number; 124 | sops.sem_op = -1; 125 | sops.sem_flg = SEM_UNDO; 126 | 127 | timeout.tv_sec = 0; 128 | timeout.tv_nsec = usecs*1000; 129 | 130 | return semtimedop(semid, &sops, 1, &timeout); 131 | } 132 | 133 | int semDecrement_timeout(int semid, int semaphore_number, int decrementBy, long usecs) 134 | { 135 | struct sembuf sops; 136 | struct timespec timeout; 137 | 138 | sops.sem_num = semaphore_number; 139 | sops.sem_op = decrementBy; 140 | sops.sem_flg = SEM_UNDO; 141 | 142 | timeout.tv_sec = 0; 143 | timeout.tv_nsec = usecs*1000; 144 | 145 | return semtimedop(semid, &sops, 1, &timeout); 146 | } -------------------------------------------------------------------------------- /examples/SerialWrapperTest.c: -------------------------------------------------------------------------------- 1 | #include "SerialWrapper.h" 2 | 3 | int main() 4 | { 5 | /* 6 | * To run this test you will need at least 4 terminals open: 7 | * 1) install socat and run: socat -d -d pty,raw,echo=1 pty,raw,echo=1 8 | * 2) should get output similiar to: 9 | * 2013/03/10 19:26:36 socat[19562] N PTY is /dev/pts/3 10 | * 2013/03/10 19:26:36 socat[19562] N PTY is /dev/pts/4 11 | * 2013/03/10 19:26:36 socat[19562] N starting data transfer loop with FDs [3,3] and [5,5] 12 | * 3) set port to '/dev/pts/3' below on line 24 13 | * 4) install minicom and run: minicom -s 14 | * 5) configure port to read on '/dev/pts/4' 15 | * 6) compile and run: make clean && make && ./SerialWrapperTest -> make sure all tests pass in terminal, 16 | * then it should be waiting to read 17 | * 7) test write: make sure data is successfully sent to minicom. should look something like this: 18 | * lots of awesome data 19 | * this is a string 20 | * Hi! 21 | * 8) test read: run: echo "this is more than ten bytes" >> /dev/pts/4 22 | * 9) make sure that SerialWrapperTest has recieved 10 bytes of data and exited successfully 23 | * 10) Rejoice! 24 | * 25 | */ 26 | 27 | int baud = 9600; 28 | int fd; 29 | int ret; 30 | char read_data[11]; 31 | char data1[] = "I am writing data to an awesome serial port!"; 32 | char data2[] = " Now give me some data to send back: "; 33 | int len; 34 | char *port; 35 | size_t n = 1024; 36 | 37 | memset(read_data, 0, 11); 38 | 39 | printf("To run this example you will need to open up another terminal first and run:\n\n"); 40 | printf("socat -d -d pty,raw,echo=1 -\n\n"); 41 | printf("Socat will allow you to attach a serial file (/dev/pts) to standard out. If you do not have socat, please install it (ie. sudo apt-get install socat).\n\n"); 42 | printf("Running this command should produce output similiar to the following:\n\n"); 43 | printf(">> socat -d -d pty,raw,echo=1 -\n"); 44 | printf("2015/07/04 11:34:47 socat[9979] N PTY is /dev/pts/8\n"); 45 | printf("2015/07/04 11:34:47 socat[9979] N reading from and writing to stdio\n"); 46 | printf("2015/07/04 11:34:47 socat[9979] N starting data transfer loop with FDs [3,3] and [0,1]\n"); 47 | printf("\nWhat serial port did socat open? (In the case above, socat opened '/dev/pts/8'): "); 48 | port = malloc(n); 49 | if( getline(&port, &n, stdin) < 0 ) { 50 | printf("Error! Reading form standard in failed!\n"); 51 | return -1; 52 | } 53 | port[strlen(port)-1] = '\0'; 54 | 55 | printf("\vOpening port: %s with baud %d\n", port, baud); 56 | if( (fd = serialOpen(port, baud)) < 0) 57 | { 58 | printf("Error! Could not open port! Make sure socat is running and you typed in the correct port!\n"); 59 | return -1; 60 | } 61 | else{ 62 | printf("Serial opened successfully with file descriptor: %d\n", fd ); 63 | } 64 | printf("\n"); 65 | 66 | printf("Flushing read port...\n"); 67 | ret = serialFlushRead(fd); 68 | printf("Flushing port returned %d\n", ret ); 69 | 70 | printf("Flushing write port...\n"); 71 | ret = serialFlushWrite(fd); 72 | printf("Flushing port returned %d\n", ret ); 73 | 74 | len = strlen(data1); 75 | printf("Writing string '%s' to port with length %d...\n", data1, len); 76 | ret = serialWrite(fd,data1,len); 77 | printf("writing returned %d\n", ret ); 78 | 79 | len = strlen(data2); 80 | printf("Writing string '%s' to port with length %d...\n", data2, len); 81 | ret = serialWrite(fd,(char*) data2,len); 82 | printf("Writing returned %d\n", ret ); 83 | 84 | printf("\nOK. Please check your 'socat' terminal. You should see some text that was written to it though the serial wrapper.\n"); 85 | printf("Now it is time to test reading from serial. Please type in some characters followed by [ENTER] into the 'socat' terminal.\n"); 86 | printf("Reading up to 10 bytes from port...\n"); 87 | while( 1 ) 88 | { 89 | ret = serialRead(fd,read_data,10); 90 | if( ret > 0 ) 91 | break; 92 | } 93 | read_data[strlen(read_data)-1] = '\0'; 94 | printf("Read %d bytes of data: %s\n", ret, read_data); 95 | 96 | printf("\nFlushing port...\n"); 97 | ret = serialFlush(fd); 98 | printf("Flushing port returned %d\n", ret ); 99 | 100 | printf("Closing port...\n"); 101 | ret = serialClose(fd); 102 | printf("Closing port returned %d\n", ret ); 103 | 104 | return 0; 105 | } 106 | -------------------------------------------------------------------------------- /SocketWrapper.c: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * File: SocketWrapper.cpp 3 | * Purpose: Provides TCP/IP communication using sockets. 4 | * Author: Kevin Dinkel 5 | **********************************************************************/ 6 | 7 | /*************************************************** 8 | * Section: Includes 9 | **************************************************/ 10 | #include "SocketWrapper.h" 11 | /*************************************************** 12 | * Function: socketCreate() 13 | * Purpose: Creates a socket for IPv4, TCP/IP. 14 | * Returns: The socket_desc on success, -1 on failure. 15 | **************************************************/ 16 | int socketCreate() 17 | { 18 | int socket_desc; 19 | int optval = 1; 20 | 21 | /* 22 | // Options: 23 | // 1) Address Family: AF_INET (IPv4) 24 | // 2) Type: SOCK_STREAM (TCP), SOCK_DGRAM (UDP) 25 | // 3) Protocol: IPPROTO_IP = 0 (IP Protocol) 26 | */ 27 | 28 | if( (socket_desc = socket(AF_INET , SOCK_STREAM , IPPROTO_IP)) < 0 ) 29 | { 30 | return errno; 31 | } 32 | 33 | /* Make sure we can reuse this port a second time on a crash: */ 34 | setsockopt(socket_desc, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); 35 | 36 | return socket_desc; 37 | } 38 | 39 | int socketBind(int socket_desc, int port) 40 | { 41 | struct sockaddr_in server; 42 | server.sin_addr.s_addr = htonl(INADDR_ANY); /* connect to any ip address associated with me, the server */ 43 | server.sin_family = AF_INET; 44 | server.sin_port = htons( port ); /* convert port number to standard network format */ 45 | 46 | if(bind(socket_desc, (struct sockaddr*)&server, sizeof(server)) < 0) 47 | { 48 | return errno; 49 | } 50 | 51 | return 0; 52 | } 53 | 54 | int socketListen(int socket_desc, int max_num_clients) 55 | { 56 | if(listen(socket_desc, max_num_clients) < 0) 57 | { 58 | return errno; 59 | } 60 | 61 | return 0; 62 | } 63 | 64 | int socketAccept(int socket_desc) 65 | { 66 | int connected_socket_desc; 67 | if( (connected_socket_desc = accept(socket_desc, (struct sockaddr*)NULL, NULL)) < 0 ) 68 | { 69 | return errno; 70 | } 71 | 72 | return connected_socket_desc; 73 | } 74 | 75 | int socketConnect(int socket_desc, char* ip_address, int port) 76 | { 77 | struct sockaddr_in server; 78 | server.sin_addr.s_addr = inet_addr(ip_address); /* convert ip string to long */ 79 | server.sin_family = AF_INET; 80 | server.sin_port = htons( port ); /* convert port number to standard network format */ 81 | 82 | if (connect(socket_desc , (struct sockaddr *)&server , sizeof(server)) < 0) 83 | { 84 | return errno; 85 | } 86 | 87 | return 0; 88 | } 89 | 90 | int socketDisconnect(int socket_desc) 91 | { 92 | return close(socket_desc); 93 | } 94 | 95 | int socketPoll(int socket_desc, int usecs) 96 | { 97 | /* 98 | // Wait for data in receive buffer or until time out before returning 99 | // Return number of bytes recieved when receive buffer has data 100 | // Return 0 on a timeoue 101 | // Return -1 on error 102 | */ 103 | int ret; 104 | struct pollfd pfd; 105 | struct timespec req; 106 | 107 | pfd.fd = socket_desc; 108 | pfd.events = POLLIN; 109 | 110 | req.tv_sec = usecs / 1000000; 111 | req.tv_nsec = (usecs % 1000000) * 1000L; 112 | 113 | if( (ret = ppoll(&pfd, 1, &req, NULL)) <= 0 ) 114 | { 115 | return ret; 116 | } 117 | 118 | return ret; 119 | } 120 | 121 | int socketSend(int socket_desc, char* message, int length) 122 | { 123 | if( length < 0 ) 124 | length = strlen(message); 125 | 126 | if( send(socket_desc , message, length, 0) < 0) 127 | { 128 | return errno; 129 | } 130 | 131 | return 0; 132 | } 133 | 134 | int socketSend_nowait(int socket_desc, char* message, int length) 135 | { 136 | if( length < 0 ) 137 | length = strlen(message); 138 | 139 | if( send(socket_desc, message, length, MSG_DONTWAIT) < 0) 140 | { 141 | return errno; 142 | } 143 | 144 | return 0; 145 | } 146 | 147 | int socketReceive(int socket_desc, char* server_reply, int length) 148 | { 149 | int ret; 150 | 151 | if( (ret = recv(socket_desc, server_reply , length , 0)) <= 0) /* len of zero means connection closed */ 152 | { 153 | return errno; 154 | } 155 | 156 | return ret; 157 | } 158 | 159 | int socketReceive_nowait(int socket_desc, char* server_reply, int length) 160 | { 161 | int ret; 162 | 163 | if( (ret = recv(socket_desc, server_reply , length , MSG_DONTWAIT)) <= 0) /* len of zero means connection closed */ 164 | { 165 | return errno; 166 | } 167 | 168 | return ret; 169 | } 170 | 171 | int socketReceive_timeout(int socket_desc, char* server_reply, int length, int usecs) 172 | { 173 | int ret; 174 | 175 | if( (ret = socketPoll(socket_desc, usecs)) <= 0 ) 176 | { 177 | return errno; 178 | } 179 | 180 | return socketReceive_nowait( socket_desc, server_reply, length); 181 | } -------------------------------------------------------------------------------- /SerialWrapper.c: -------------------------------------------------------------------------------- 1 | #include "SerialWrapper.h" 2 | 3 | int serialOpen(char* port_address, int baud_rate) 4 | { 5 | /* Open device: */ 6 | int fd; 7 | struct termios options; 8 | if( (fd = open(port_address, O_RDWR | O_NOCTTY | O_NDELAY)) < 0) 9 | { 10 | return -1; 11 | } 12 | 13 | /* If port opened, set up our parameters: */ 14 | /* fcntl(fd, F_SETFL, FNDELAY); // non-blocking read */ 15 | fcntl(fd, F_SETFL,0); /* blocking read */ 16 | 17 | /* Save current port settings so nothing is corrupt on exit: */ 18 | tcgetattr(fd, &options); 19 | cfmakeraw(&options); 20 | 21 | /* Convert integer baud to baud type: */ 22 | /* Default to 9600 baud if none specified: */ 23 | switch (baud_rate) 24 | { 25 | case 4800: 26 | cfsetispeed(&options, B4800); 27 | cfsetospeed(&options, B4800); 28 | break; 29 | case 9600: 30 | cfsetispeed(&options, B9600); 31 | cfsetospeed(&options, B9600); 32 | break; 33 | case 19200: 34 | cfsetispeed(&options, B19200); 35 | cfsetospeed(&options, B19200); 36 | break; 37 | case 38400: 38 | cfsetispeed(&options, B38400); 39 | cfsetospeed(&options, B38400); 40 | break; 41 | case 57600: 42 | cfsetispeed(&options, B57600); 43 | cfsetospeed(&options, B57600); 44 | break; 45 | case 115200: 46 | cfsetispeed(&options, B115200); 47 | cfsetospeed(&options, B115200); 48 | break; 49 | case 230400: 50 | cfsetispeed(&options, B230400); 51 | cfsetospeed(&options, B230400); 52 | break; 53 | case 500000: 54 | cfsetispeed(&options, B500000); 55 | cfsetospeed(&options, B500000); 56 | break; 57 | default: 58 | cfsetispeed(&options, B9600); 59 | cfsetospeed(&options, B9600); 60 | break; 61 | } 62 | 63 | /* Set options for proper port settings: */ 64 | options.c_cflag |= (CLOCAL | CREAD); 65 | 66 | /* Turn off hardware flow control: */ 67 | options.c_cflag &= ~CRTSCTS; 68 | options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); 69 | options.c_cflag &= ~PARENB; 70 | options.c_cflag &= ~CSTOPB; 71 | options.c_cflag &= ~CSIZE; 72 | options.c_cflag |= CS8; 73 | 74 | /* Write our changes to the port configuration: */ 75 | tcsetattr(fd, TCSANOW, &options); 76 | 77 | return fd; 78 | } 79 | 80 | int serialFlush(int fd) 81 | { 82 | if(tcflush(fd,TCIOFLUSH) == -1) 83 | { 84 | return -1; 85 | } 86 | 87 | return 0; 88 | } 89 | 90 | int serialFlushWrite(int fd) 91 | { 92 | if(tcflush(fd,TCOFLUSH) == -1) 93 | { 94 | return -1; 95 | } 96 | 97 | return 0; 98 | } 99 | 100 | int serialFlushRead(int fd) 101 | { 102 | if(tcflush(fd,TCIFLUSH) == -1) 103 | { 104 | return -1; 105 | } 106 | 107 | return 0; 108 | } 109 | 110 | int serialWrite(int fd, char* data, int length) 111 | { 112 | if(write(fd,data,length)==-1) 113 | { 114 | return -1; 115 | } 116 | 117 | return 0; 118 | } 119 | 120 | int serialRead(int fd, char* temp, int length) 121 | { 122 | int cnt; 123 | 124 | if((cnt = read(fd,temp,length))==-1) 125 | { 126 | return -1; 127 | } 128 | 129 | return cnt; 130 | } 131 | 132 | int serialCommandByDelim(int fd, char* cmd, char* reply, int replyLength, int usecs, char delim) 133 | { 134 | int bufferCount = 0; 135 | int index = 0; 136 | char temp; 137 | timer timerid; 138 | 139 | /* Sleep for half a second before checking timeout, unless it should be smaller. */ 140 | int sleeptime = HALF_SECOND; 141 | int st = usecs / 10; 142 | if ( sleeptime > st ) 143 | { 144 | sleeptime = st; 145 | } 146 | 147 | /* Create timeout timer: */ 148 | timerCreate(&timerid); 149 | timerSet_us(&timerid, usecs); 150 | 151 | /* Flush the read port: */ 152 | if ( serialFlushRead(fd) < 0) 153 | { 154 | timerDelete(&timerid); 155 | return -1; 156 | } 157 | 158 | /* Write the command: */ 159 | if ( serialWrite(fd, cmd, strlen(cmd)) < 0) 160 | { 161 | timerDelete(&timerid); 162 | return -1; 163 | } 164 | 165 | /* Wait for response: */ 166 | while( !isTimerExpired(&timerid) ) 167 | { 168 | if( (bufferCount = serialBufferCount( fd )) > 0 ) 169 | { 170 | if( serialRead( fd, &temp, 1 ) < 0 ) 171 | { 172 | timerDelete(&timerid); 173 | return -1; 174 | } 175 | 176 | /* Have we found the delimter yet? */ 177 | if( temp == delim ) 178 | { 179 | timerDelete(&timerid); 180 | return index; 181 | } 182 | 183 | reply[index] = temp; 184 | index++; 185 | 186 | if( index >= replyLength ) 187 | { 188 | timerDelete(&timerid); 189 | return index; 190 | } 191 | } 192 | else 193 | { 194 | rt_sleep_us( sleeptime ); 195 | } 196 | } 197 | 198 | timerDelete(&timerid); 199 | return index; 200 | } 201 | 202 | int serialCommandByLength(int fd, char* cmd, char* reply, int replyLength, int usecs) 203 | { 204 | int bufferCount = 0; 205 | timer timerid; 206 | 207 | /* Sleep for half a second before checking timeout, unless it should be smaller. */ 208 | int sleeptime = HALF_SECOND; 209 | int st = usecs / 10; 210 | if ( sleeptime > st ) 211 | { 212 | sleeptime = st; 213 | } 214 | 215 | /* Create timeout timer: */ 216 | timerCreate(&timerid); 217 | timerSet_us(&timerid, usecs); 218 | 219 | /* Flush the read port: */ 220 | if ( serialFlushRead(fd) < 0) 221 | { 222 | timerDelete(&timerid); 223 | return -1; 224 | } 225 | 226 | /* Write the command: */ 227 | if ( serialWrite(fd, cmd, strlen(cmd)) < 0) 228 | { 229 | timerDelete(&timerid); 230 | return -1; 231 | } 232 | 233 | /* Wait for response: */ 234 | while ( (bufferCount = serialBufferCount( fd )) < replyLength ) 235 | { 236 | if( isTimerExpired(&timerid) ) 237 | { 238 | bufferCount = serialBufferCount( fd ); 239 | break; 240 | } 241 | 242 | rt_sleep_us( sleeptime ); 243 | } 244 | 245 | /* Make sure we don't read more data than was asked for... */ 246 | if( bufferCount > replyLength ) 247 | { 248 | bufferCount = replyLength; 249 | } 250 | 251 | bufferCount = serialRead( fd, reply, bufferCount ); 252 | 253 | timerDelete(&timerid); 254 | return bufferCount; 255 | } 256 | 257 | int serialBufferCount(int fd) 258 | { 259 | int count; 260 | 261 | ioctl(fd, FIONREAD, &count); 262 | 263 | return count; 264 | } 265 | 266 | int serialClose(int fd) 267 | { 268 | return close(fd); 269 | } -------------------------------------------------------------------------------- /MessageQueueWrapper.c: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * File: messageQueueWrapper.c 3 | * Purpose: Provides IPC using message queues. 4 | * Author: Kevin Dinkel 5 | **********************************************************************/ 6 | 7 | /*************************************************** 8 | * Section: Includes 9 | **************************************************/ 10 | #include "MessageQueueWrapper.h" 11 | /*************************************************** 12 | * Function: messageQueueGet(key_t key, int p) 13 | * Param key: A key (from ftok) used to create a queue. 14 | * Param p: The priority level of the queue you are creating. 15 | * Purpose: Creates a queue based on key. 16 | * Returns: The qid on success, -1 on failure. 17 | **************************************************/ 18 | int messageQueueGet(key_t key) 19 | { 20 | int qid; 21 | if ((qid = msgget(key, 0666)) == -1) 22 | return -1; 23 | 24 | return qid; 25 | } 26 | /*************************************************** 27 | * Function: messageQueueCreate(key_t key, int p) 28 | * Param key: A key (from ftok) used to create a queue. 29 | * Param p: The priority level of the queue you are creating. 30 | * Purpose: Creates a queue based on key. 31 | * Returns: The qid on success, -1 on failure. 32 | **************************************************/ 33 | int messageQueueCreate(key_t key) 34 | { 35 | int qid; 36 | struct msqid_ds buf; 37 | 38 | if ((qid = msgget(key, IPC_CREAT | 0666)) == -1) 39 | return -1; 40 | 41 | /* increase message queue size */ 42 | if (msgctl(qid, IPC_STAT, &buf) == -1) 43 | return -1; 44 | 45 | /* set new buffer size */ 46 | buf.msg_qbytes = 16384; /* look at ipcs -l */ 47 | 48 | /* set Queue values */ 49 | if (msgctl(qid, IPC_SET, &buf) == -1) 50 | return -1; 51 | 52 | return qid; 53 | } 54 | /********************************************************* 55 | * Function: messageQueueDelete(int qid) 56 | * Param qid: The queue ID of the message queue to be deleted. 57 | * Purpose: Deletes a message queue to release system resources. 58 | * Returns: -1 on failure, 0 on success. 59 | *********************************************************/ 60 | int messageQueueDelete(int qid) 61 | { 62 | return msgctl(qid, IPC_RMID, NULL); 63 | } 64 | /**************************************************** 65 | * Function: messageQueueSend(int qid, BMsg *msg) 66 | * Param qid: The queue ID of the message queue. 67 | * Param msg: A BMsg struct that has been initialized 68 | * and will be sent over the message queue 69 | * Purpose: Sends a message over a queue denoted by qid 70 | * Returns: -1 on failure, 0 on success. 71 | ****************************************************/ 72 | int messageQueueSend(int qid, Message* msg) 73 | { 74 | /* 75 | struct msqid_ds buf; 76 | int temp; 77 | temp = msgctl(qid, IPC_STAT, &buf); 78 | if (temp == -1) { 79 | (void) fprintf(stderr, "msgctl fail"); 80 | } 81 | else { 82 | cerr << "msg_perm.uid = "<< buf.msg_perm.uid<< endl; 83 | cerr << "msg_perm.gid = "<< buf.msg_perm.gid<< endl; 84 | cerr << "msg_perm.cuid = "<< buf.msg_perm.cuid<< endl; 85 | cerr << "msg_perm.cgid = "<< buf.msg_perm.cgid<< endl; 86 | cerr << "msg_perm.mode = "<< buf.msg_perm.mode; 87 | cerr << " access permissions = "<< (buf.msg_perm.mode & 0777)<< endl; 88 | cerr << "msg_cbytes = "<< buf.msg_cbytes<< endl; 89 | cerr << "msg_qbytes = "<< buf.msg_qbytes<< endl; 90 | cerr << "msg_qnum = "<< buf.msg_qnum<< endl; 91 | cerr << "msg_lspid = "<< buf.msg_lspid<< endl; 92 | cerr << "msg_lrpid = "<< buf.msg_lrpid << endl; 93 | } 94 | */ 95 | int ret; 96 | if ((ret = msgsnd(qid, msg, sizeof(Message) - sizeof(long), 0)) == -1) 97 | { 98 | msg->err=errno; 99 | return -1; 100 | } 101 | return ret; 102 | } 103 | 104 | int messageQueueSend_nowait(int qid, Message* msg) 105 | { 106 | int ret; 107 | if ((ret = msgsnd(qid, msg, sizeof(Message) - sizeof(long), IPC_NOWAIT)) == -1) 108 | { 109 | msg->err=errno; 110 | return -1; 111 | } 112 | return ret; 113 | } 114 | 115 | int messageQueueSend_timeout(int qid, Message* msg, int usecs) 116 | { 117 | int ret; 118 | timer timerid; 119 | int sleeptime = 500000; 120 | int st = usecs / 10; 121 | 122 | /* Sleep for half a second before checking timeout, unless it should be smaller. */ 123 | if ( sleeptime > st ) 124 | { 125 | sleeptime = st; 126 | } 127 | 128 | /* Create timeout timer: */ 129 | timerCreate(&timerid); 130 | timerSet_us(&timerid, usecs); 131 | 132 | /* Reset errno to zero: */ 133 | errno = 0; 134 | 135 | /* Get message: */ 136 | while( (ret = msgsnd(qid, msg, sizeof(Message) - sizeof(long), IPC_NOWAIT)) < 0 ) 137 | { 138 | if( errno != ENOMSG ) 139 | { 140 | msg->err=errno; 141 | timerDelete(&timerid); 142 | return -1; 143 | } 144 | 145 | if( isTimerExpired(&timerid) ) 146 | { 147 | msg->err=errno; 148 | timerDelete(&timerid); 149 | return -1; /* return -1 here not 0 because it is a send */ 150 | } 151 | 152 | rt_sleep_us( sleeptime ); 153 | } 154 | 155 | timerDelete(&timerid); 156 | 157 | return ret; 158 | } 159 | 160 | /******************************************************* 161 | * Function: messageQueueReceive(int qid, long type, MMsg *msg) 162 | * Param qid: The queue ID of the message queue. 163 | * Param type: The specific type of message you want to get. 164 | * Can be any integer. 165 | * Param msg: A MMsg struct that will store the return data. 166 | * Purpose: Receives a message from the message queue. 167 | * Returns: -1 on failure, 0 on success. 168 | *********************************************************/ 169 | int messageQueueReceive(int qid, Message* msg, long type) 170 | { 171 | int ret; 172 | if ((ret = msgrcv(qid, msg, sizeof(Message) - sizeof(long), type, 0)) == -1) 173 | { 174 | msg->err=errno; 175 | return -1; 176 | } 177 | return ret; 178 | } 179 | 180 | int messageQueueReceive_nowait(int qid, Message* msg, long type) 181 | { 182 | int ret; 183 | if ((ret = msgrcv(qid, msg, sizeof(Message) - sizeof(long), type, IPC_NOWAIT)) == -1) 184 | { 185 | msg->err=errno; 186 | return -1; 187 | } 188 | return ret; 189 | } 190 | 191 | int messageQueueReceive_timeout(int qid, Message* msg, int usecs, long type) 192 | { 193 | int ret; 194 | timer timerid; 195 | int sleeptime = 500000; 196 | int st = usecs / 10; 197 | 198 | /* Sleep for half a second before checking timeout, unless it should be smaller. */ 199 | if ( sleeptime > st ) 200 | { 201 | sleeptime = st; 202 | } 203 | 204 | /* Create timeout timer: */ 205 | timerCreate(&timerid); 206 | timerSet_us(&timerid, usecs); 207 | 208 | /* Reset errno to zero: */ 209 | errno = 0; 210 | 211 | /* Get message: */ 212 | while( (ret = msgrcv(qid, msg, sizeof(Message) - sizeof(long), type, IPC_NOWAIT)) < 0 ) 213 | { 214 | if( errno != ENOMSG ) 215 | { 216 | msg->err=errno; 217 | timerDelete(&timerid); 218 | return -1; 219 | } 220 | 221 | if( isTimerExpired(&timerid) ) 222 | { 223 | msg->err=errno; 224 | timerDelete(&timerid); 225 | return 0; /* return 0 here because no bytes returned */ 226 | } 227 | 228 | rt_sleep_us( sleeptime ); 229 | } 230 | 231 | timerDelete(&timerid); 232 | return ret; 233 | } 234 | -------------------------------------------------------------------------------- /TimerWrapper.c: -------------------------------------------------------------------------------- 1 | #include "TimerWrapper.h" 2 | 3 | int timerCreate(timer* timerid) 4 | { 5 | /* 6 | // Create monotonic clock. It does not rely on the 7 | // system-wide real-time "settable" clock. 8 | // The monotonic clock is unsettable and is 9 | // good for relative timing... 10 | // Don't send signal on timer notify: 11 | */ 12 | struct sigevent sevp; 13 | sevp.sigev_notify = SIGEV_NONE; 14 | 15 | if( timer_create(CLOCK_MONOTONIC, &sevp, &timerid->timerid) < 0) 16 | { 17 | return -1; 18 | } 19 | 20 | return 0; 21 | } 22 | 23 | int timerDelete(timer* timerid) 24 | { 25 | return timer_delete(timerid->timerid); 26 | } 27 | 28 | int timerSet(timer* timerid, const time_t sec, const long nsec) 29 | { 30 | struct itimerspec timer; 31 | 32 | /* Disable interval timing, we want a "one-shot" timer: */ 33 | timer.it_interval.tv_sec = 0; 34 | timer.it_interval.tv_nsec = 0; 35 | 36 | /* Set timer to expire at desired relative time: */ 37 | timer.it_value.tv_sec = sec; 38 | timer.it_value.tv_nsec = nsec; 39 | 40 | if( timer_settime(timerid->timerid, 0, &timer, NULL) < 0 ) 41 | { 42 | return -1; 43 | } 44 | 45 | return 0; 46 | } 47 | 48 | int timerSet_us(timer* timerid, const long usec) 49 | { 50 | struct itimerspec timer; 51 | 52 | /* Disable interval timing, we want a "one-shot" timer: */ 53 | timer.it_interval.tv_sec = 0; 54 | timer.it_interval.tv_nsec = 0; 55 | 56 | /* Set timer to expire at desired relative time: */ 57 | timer.it_value.tv_sec = usec / 1000000; 58 | timer.it_value.tv_nsec = (usec % 1000000) * 1000; 59 | 60 | if( timer_settime(timerid->timerid, 0, &timer, NULL) < 0 ) 61 | { 62 | return -1; 63 | } 64 | 65 | return 0; 66 | } 67 | 68 | int timerUnset(timer* timerid) 69 | { 70 | struct itimerspec timer; 71 | 72 | /* Disable timer: */ 73 | timer.it_value.tv_sec = 0; 74 | timer.it_value.tv_nsec = 0L; 75 | timer.it_interval.tv_sec = 0; 76 | timer.it_interval.tv_nsec = 0L; 77 | 78 | if( timer_settime(timerid->timerid, 0, &timer, NULL) < 0 ) 79 | { 80 | return -1; 81 | } 82 | 83 | return 0; 84 | } 85 | 86 | int timerGet(timer* timerid, time_t* sec, long* nsec) 87 | { 88 | struct itimerspec timer; 89 | 90 | if( timer_gettime(timerid->timerid, &timer) < 0) 91 | { 92 | return -1; 93 | } 94 | 95 | *sec = timer.it_value.tv_sec; 96 | *nsec = timer.it_value.tv_nsec; 97 | 98 | return 0; 99 | } 100 | 101 | int isTimerExpired(timer* timerid) 102 | { 103 | time_t sec; 104 | long nsec; 105 | 106 | if( timerGet( timerid, &sec, &nsec) < 0 ) 107 | { 108 | return 1; /* on an error, assume timer has expired so we don't block forever */ 109 | } 110 | 111 | if( (sec > 0) || (nsec > 0) ) 112 | { 113 | return 0; 114 | } 115 | 116 | return 1; 117 | } 118 | 119 | /* ////////////////////////////////////////////////////////////////// 120 | /////////////////////////////////////////////////////////////////// */ 121 | int periodicTimerCreate(periodicTimer* pt, long threadId, int signalNum) 122 | { 123 | /* 124 | // Create monotonic clock. It does not rely on the 125 | // system-wide real-time "settable" clock. 126 | // The monotonic clock is unsettable and is 127 | // good for relative timing... 128 | // Send a signal on timer expiration: 129 | */ 130 | struct sigevent sevp; 131 | if( threadId >= 0 ) 132 | { 133 | /* 134 | // If thread id is given notify only 135 | // that specific thread. 136 | */ 137 | sevp.sigev_notify = SIGEV_THREAD_ID; 138 | sevp._sigev_un._tid = threadId; 139 | /* 140 | // same as sigev_notify_thread_id 141 | // see here: http://stackoverflow.com/questions/16826898/error-struct-sigevent-has-no-member-named-sigev-notify-thread-id 142 | */ 143 | } 144 | else 145 | { 146 | /* Otherwise notify the entire process. */ 147 | sevp.sigev_notify = SIGEV_SIGNAL; 148 | } 149 | 150 | /* Send an alarm signal: */ 151 | pt->signum = signalNum; 152 | sevp.sigev_signo = pt->signum; 153 | 154 | /* Allow alarm signal to be caught: */ 155 | sigemptyset(&pt->set); 156 | sigaddset(&pt->set, pt->signum); 157 | sigprocmask(SIG_BLOCK, &pt->set, NULL); 158 | 159 | if( timer_create(CLOCK_MONOTONIC, &sevp, &pt->timerid) < 0) 160 | { 161 | return -1; 162 | } 163 | 164 | pt->enabled = 1; 165 | 166 | return 0; 167 | } 168 | 169 | int periodicTimerDelete(periodicTimer* pt) 170 | { 171 | /* Disallow alarm signal to be caught: */ 172 | sigemptyset(&pt->set); 173 | sigaddset(&pt->set, pt->signum); 174 | sigprocmask(SIG_UNBLOCK, &pt->set, NULL); 175 | 176 | return timer_delete(pt->timerid); 177 | } 178 | 179 | int periodicTimerSet(periodicTimer* pt, const time_t sec, const long nsec) 180 | { 181 | struct itimerspec timer; 182 | 183 | /* Enable interval timing, we want a "periodic" timer: */ 184 | timer.it_interval.tv_sec = sec; 185 | timer.it_interval.tv_nsec = nsec; 186 | 187 | /* Set timer to expire at desired relative time: */ 188 | timer.it_value.tv_sec = sec; 189 | timer.it_value.tv_nsec = nsec; 190 | 191 | if( timer_settime(pt->timerid, 0, &timer, NULL) < 0 ) 192 | { 193 | return -1; 194 | } 195 | 196 | return 0; 197 | } 198 | 199 | int periodicTimerSet_us(periodicTimer* pt, const long usec) 200 | { 201 | struct itimerspec timer; 202 | 203 | /* Enable interval timing, we want a "periodic" timer: */ 204 | timer.it_interval.tv_sec = usec / 1000000; 205 | timer.it_interval.tv_nsec = (usec % 1000000) * 1000; 206 | 207 | /* Set timer to expire at desired relative time: */ 208 | timer.it_value.tv_sec = usec / 1000000; 209 | timer.it_value.tv_nsec = (usec % 1000000) * 1000; 210 | 211 | if( timer_settime(pt->timerid, 0, &timer, NULL) < 0 ) 212 | { 213 | return -1; 214 | } 215 | 216 | return 0; 217 | } 218 | 219 | int periodicTimerUnset(periodicTimer* pt) 220 | { 221 | struct itimerspec timer; 222 | 223 | /* Disable timer: */ 224 | timer.it_value.tv_sec = 0; 225 | timer.it_value.tv_nsec = 0L; 226 | timer.it_interval.tv_sec = 0; 227 | timer.it_interval.tv_nsec = 0L; 228 | 229 | if( timer_settime(pt->timerid, 0, &timer, NULL) < 0 ) 230 | { 231 | return -1; 232 | } 233 | 234 | return 0; 235 | } 236 | 237 | int periodicTimerGet(periodicTimer* pt, time_t* sec, long* nsec) 238 | { 239 | struct itimerspec timer; 240 | 241 | if( timer_gettime(pt->timerid, &timer) < 0) 242 | { 243 | return -1; 244 | } 245 | 246 | *sec = timer.it_value.tv_sec; 247 | *nsec = timer.it_value.tv_nsec; 248 | 249 | return 0; 250 | } 251 | 252 | int periodicTimerIntervalGet(periodicTimer* pt, time_t* sec, long* nsec) 253 | { 254 | struct itimerspec timer; 255 | 256 | if( timer_gettime(pt->timerid, &timer) < 0) 257 | { 258 | return -1; 259 | } 260 | 261 | *sec = timer.it_interval.tv_sec; 262 | *nsec = timer.it_interval.tv_nsec; 263 | 264 | return 0; 265 | } 266 | 267 | int isPeriodicTimerSet(periodicTimer* pt) 268 | { 269 | time_t sec; 270 | long nsec; 271 | 272 | if( periodicTimerIntervalGet( pt, &sec, &nsec ) < 0 ) 273 | { 274 | return 0; 275 | } 276 | 277 | if( (sec > 0) || (nsec > 0) ) 278 | { 279 | return 1; 280 | } 281 | 282 | return 0; 283 | } 284 | 285 | void periodicTimerEnable(periodicTimer* pt) 286 | { 287 | pt->enabled = 1; 288 | } 289 | 290 | void periodicTimerDisable(periodicTimer* pt) 291 | { 292 | pt->enabled = 0; 293 | } 294 | 295 | int isPeriodicTimerEnabled(periodicTimer* pt) 296 | { 297 | return pt->enabled; 298 | } 299 | 300 | int periodicTimerWait(periodicTimer* pt, long sec, long nsec) 301 | { 302 | struct timespec timeout; 303 | int sig; 304 | 305 | if(!pt->enabled) 306 | return pt->signum; 307 | 308 | if( sec >= 0 || nsec >= 0 ) 309 | { 310 | timeout.tv_sec = sec; 311 | timeout.tv_nsec = nsec; 312 | 313 | if( (sig = sigtimedwait(&pt->set, NULL, &timeout)) < 0 ) 314 | { 315 | if( errno == EAGAIN ) 316 | { 317 | return 0; 318 | } 319 | 320 | return -1; 321 | } 322 | 323 | return sig; 324 | } 325 | else 326 | { 327 | return sigwaitinfo(&pt->set, NULL); 328 | } 329 | 330 | return 0; 331 | } 332 | 333 | /* /////////////////////////////////////////////////////////////////// 334 | /////////////////////////////////////////////////////////////////// */ 335 | int stopWatchStart(stopWatch* sw) 336 | { 337 | return clock_gettime(CLOCK_MONOTONIC, &sw->start_t); 338 | } 339 | 340 | int stopWatchStop(stopWatch* sw) 341 | { 342 | return clock_gettime(CLOCK_MONOTONIC, &sw->stop_t); 343 | } 344 | 345 | long stopWatchReport(stopWatch* sw) 346 | { 347 | return (sw->stop_t.tv_sec*1000000000 + sw->stop_t.tv_nsec) - (sw->start_t.tv_sec*1000000000 + sw->start_t.tv_nsec); 348 | } 349 | 350 | /* /////////////////////////////////////////////////////////////////// 351 | /////////////////////////////////////////////////////////////////// */ 352 | int rt_sleep(const time_t sec, const long nsec) 353 | { 354 | struct timespec ts; 355 | int status; 356 | ts.tv_sec = sec; 357 | ts.tv_nsec = nsec; 358 | 359 | do { 360 | status = clock_nanosleep(CLOCK_MONOTONIC, 361 | 0, &ts, &ts); 362 | } while(status == EINTR); 363 | /* Continue sleeping if interupted by signal handler */ 364 | return status; 365 | } 366 | 367 | int rt_sleep_us(const long usec) 368 | { 369 | struct timespec ts; 370 | int status; 371 | ts.tv_sec = usec / 1000000; 372 | ts.tv_nsec = (usec % 1000000) * 1000; 373 | 374 | do { 375 | status = clock_nanosleep(CLOCK_MONOTONIC, 376 | 0, &ts, &ts); 377 | } while(status == EINTR); 378 | /* Continue sleeping if interupted by signal handler */ 379 | return status; 380 | } 381 | 382 | /* /////////////////////////////////////////////////////////////////// 383 | /////////////////////////////////////////////////////////////////// */ 384 | extern int rt_time( time_t* sec, long* nsec ) 385 | { 386 | struct timespec timeSpec; 387 | int ret = clock_gettime(CLOCK_REALTIME, &timeSpec); 388 | *sec = timeSpec.tv_sec; 389 | *nsec = timeSpec.tv_nsec; 390 | return ret; 391 | } 392 | 393 | extern int rt_time_ts( struct timespec* timeSpec ) 394 | { 395 | return clock_gettime(CLOCK_REALTIME, timeSpec); 396 | } 397 | 398 | /* return nanosecond timestamp */ 399 | unsigned long rt_time_ns() 400 | { 401 | struct timespec timeSpec; 402 | clock_gettime(CLOCK_REALTIME, &timeSpec); 403 | return (timeSpec.tv_sec*1000000000 + timeSpec.tv_nsec); 404 | } 405 | 406 | unsigned long rt_time_tsns(struct timespec* timeSpecStruct) 407 | { 408 | return (timeSpecStruct->tv_sec*1000000000 + timeSpecStruct->tv_nsec); 409 | } 410 | 411 | /* /////////////////////////////////////////////////////////////////// 412 | //////////////////////////////////////////////////////////// */ 413 | void usec_2_sec_nsec(long usec, time_t* sec, long* nsec) 414 | { 415 | *sec = usec / 1000000; 416 | *nsec = (usec % 1000000) * 1000; 417 | } 418 | --------------------------------------------------------------------------------