From 07338ff2a9b84e1ab752c681bc7b9a35851ef423 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 6 Apr 2017 11:58:55 -0600 Subject: [PATCH 1/6] examples/udpblaster: Add logic to bind the local UDP socket to a well-known address. --- examples/udpblaster/udpblaster.h | 8 +++- examples/udpblaster/udpblaster_host.c | 4 +- examples/udpblaster/udpblaster_target.c | 59 ++++++++++++++++++------- 3 files changed, 53 insertions(+), 18 deletions(-) diff --git a/examples/udpblaster/udpblaster.h b/examples/udpblaster/udpblaster.h index fdfe1b7d8..8ae5cad5e 100644 --- a/examples/udpblaster/udpblaster.h +++ b/examples/udpblaster/udpblaster.h @@ -74,7 +74,13 @@ # define PF_INETX PF_INET #endif -#define UDPBLASTER_PORTNO 5471 +#ifdef CONFIG_NET_6LOWPAN +# define UDPBLASTER_HOST_PORTNO 0xf0b0 +# define UDPBLASTER_TARGET_PORTNO 0xf0b1 +#else +# define UDPBLASTER_HOST_PORTNO 5471 +# define UDPBLASTER_TARGET_PORTNO 5472 +#endif #define ETH_HDRLEN 14 /* Size of the Ethernet header */ #define IPv4_HDRLEN 20 /* Size of IPv4 header */ diff --git a/examples/udpblaster/udpblaster_host.c b/examples/udpblaster/udpblaster_host.c index 11562d84d..67f3067d4 100644 --- a/examples/udpblaster/udpblaster_host.c +++ b/examples/udpblaster/udpblaster_host.c @@ -69,7 +69,7 @@ int main(int argc, char **argv, char **envp) #ifdef CONFIG_EXAMPLES_UDPBLASTER_IPv4 target.sin_family = AF_INET; - target.sin_port = HTONS(UDPBLASTER_PORTNO); + target.sin_port = HTONS(UDPBLASTER_TARGET_PORTNO); target.sin_addr.s_addr = HTONL(CONFIG_EXAMPLES_UDPBLASTER_TARGETIP); addrlen = sizeof(struct sockaddr_in); @@ -82,7 +82,7 @@ int main(int argc, char **argv, char **envp) #else target.sin6_family = AF_INET6; - target.sin6_port = HTONS(UDPBLASTER_PORTNO); + target.sin6_port = HTONS(UDPBLASTER_TARGET_PORTNO); target.sin6_addr.s6_addr16[0] = HTONS(CONFIG_EXAMPLES_UDPBLASTER_TARGETIPv6_1); target.sin6_addr.s6_addr16[1] = HTONS(CONFIG_EXAMPLES_UDPBLASTER_TARGETIPv6_2); target.sin6_addr.s6_addr16[2] = HTONS(CONFIG_EXAMPLES_UDPBLASTER_TARGETIPv6_3); diff --git a/examples/udpblaster/udpblaster_target.c b/examples/udpblaster/udpblaster_target.c index afbb1b51b..7f0e286ba 100644 --- a/examples/udpblaster/udpblaster_target.c +++ b/examples/udpblaster/udpblaster_target.c @@ -192,8 +192,10 @@ int udpblaster_main(int argc, char *argv[]) { #ifdef CONFIG_EXAMPLES_UDPBLASTER_IPv4 struct sockaddr_in host; + struct sockaddr_in target; #else struct sockaddr_in6 host; + struct sockaddr_in6 target; #endif socklen_t addrlen; int npackets; @@ -209,10 +211,9 @@ int udpblaster_main(int argc, char *argv[]) #ifdef CONFIG_EXAMPLES_UDPBLASTER_IPv4 host.sin_family = AF_INET; - host.sin_port = HTONS(UDPBLASTER_PORTNO); + host.sin_port = HTONS(UDPBLASTER_HOST_PORTNO); host.sin_addr.s_addr = HTONL(CONFIG_EXAMPLES_UDPBLASTER_HOSTIP); - addrlen = sizeof(struct sockaddr_in); sockfd = socket(PF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { @@ -220,25 +221,53 @@ int udpblaster_main(int argc, char *argv[]) return 1; } -#else - host.sin6_family = AF_INET6; - host.sin6_port = HTONS(UDPBLASTER_PORTNO); - host.sin6_addr.s6_addr16[0] = HTONS(CONFIG_EXAMPLES_UDPBLASTER_HOSTIPv6_1); - host.sin6_addr.s6_addr16[1] = HTONS(CONFIG_EXAMPLES_UDPBLASTER_HOSTIPv6_2); - host.sin6_addr.s6_addr16[2] = HTONS(CONFIG_EXAMPLES_UDPBLASTER_HOSTIPv6_3); - host.sin6_addr.s6_addr16[3] = HTONS(CONFIG_EXAMPLES_UDPBLASTER_HOSTIPv6_4); - host.sin6_addr.s6_addr16[4] = HTONS(CONFIG_EXAMPLES_UDPBLASTER_HOSTIPv6_5); - host.sin6_addr.s6_addr16[5] = HTONS(CONFIG_EXAMPLES_UDPBLASTER_HOSTIPv6_6); - host.sin6_addr.s6_addr16[6] = HTONS(CONFIG_EXAMPLES_UDPBLASTER_HOSTIPv6_7); - host.sin6_addr.s6_addr16[7] = HTONS(CONFIG_EXAMPLES_UDPBLASTER_HOSTIPv6_8); + target.sin_family = AF_INET; + target.sin_port = HTONS(UDPBLASTER_TARGET_PORTNO); + target.sin_addr.s_addr = HTONL(CONFIG_EXAMPLES_UDPBLASTER_TARGETIP); + addrlen = sizeof(struct sockaddr_in); - addrlen = sizeof(struct sockaddr_in6); - sockfd = socket(PF_INET6, SOCK_DGRAM, 0); + if (bind(sockfd, (struct sockaddr*)&target, addrlen) < 0) + { + printf("server: ERROR bind failure: %d\n", errno); + return 1; + } + +#else + host.sin6_family = AF_INET6; + host.sin6_port = HTONS(UDPBLASTER_HOST_PORTNO); + host.sin6_addr.s6_addr16[0] = HTONS(CONFIG_EXAMPLES_UDPBLASTER_HOSTIPv6_1); + host.sin6_addr.s6_addr16[1] = HTONS(CONFIG_EXAMPLES_UDPBLASTER_HOSTIPv6_2); + host.sin6_addr.s6_addr16[2] = HTONS(CONFIG_EXAMPLES_UDPBLASTER_HOSTIPv6_3); + host.sin6_addr.s6_addr16[3] = HTONS(CONFIG_EXAMPLES_UDPBLASTER_HOSTIPv6_4); + host.sin6_addr.s6_addr16[4] = HTONS(CONFIG_EXAMPLES_UDPBLASTER_HOSTIPv6_5); + host.sin6_addr.s6_addr16[5] = HTONS(CONFIG_EXAMPLES_UDPBLASTER_HOSTIPv6_6); + host.sin6_addr.s6_addr16[6] = HTONS(CONFIG_EXAMPLES_UDPBLASTER_HOSTIPv6_7); + host.sin6_addr.s6_addr16[7] = HTONS(CONFIG_EXAMPLES_UDPBLASTER_HOSTIPv6_8); + + sockfd = socket(PF_INET6, SOCK_DGRAM, 0); if (sockfd < 0) { fprintf(stderr, "ERROR: socket() failed: %d\n", errno); return 1; } + + target.sin6_family = AF_INET6; + target.sin6_port = HTONS(UDPBLASTER_TARGET_PORTNO); + target.sin6_addr.s6_addr16[0] = HTONS(CONFIG_EXAMPLES_UDPBLASTER_TARGETIPv6_1); + target.sin6_addr.s6_addr16[1] = HTONS(CONFIG_EXAMPLES_UDPBLASTER_TARGETIPv6_2); + target.sin6_addr.s6_addr16[2] = HTONS(CONFIG_EXAMPLES_UDPBLASTER_TARGETIPv6_3); + target.sin6_addr.s6_addr16[3] = HTONS(CONFIG_EXAMPLES_UDPBLASTER_TARGETIPv6_4); + target.sin6_addr.s6_addr16[4] = HTONS(CONFIG_EXAMPLES_UDPBLASTER_TARGETIPv6_5); + target.sin6_addr.s6_addr16[5] = HTONS(CONFIG_EXAMPLES_UDPBLASTER_TARGETIPv6_6); + target.sin6_addr.s6_addr16[6] = HTONS(CONFIG_EXAMPLES_UDPBLASTER_TARGETIPv6_7); + target.sin6_addr.s6_addr16[7] = HTONS(CONFIG_EXAMPLES_UDPBLASTER_TARGETIPv6_8); + addrlen = sizeof(struct sockaddr_in6); + + if (bind(sockfd, (struct sockaddr*)&target, addrlen) < 0) + { + printf("server: ERROR bind failure: %d\n", errno); + return 1; + } #endif npackets = 0; From 194c2d86a85e044eb2160de1c2705ba50d2298f2 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 6 Apr 2017 16:00:41 -0600 Subject: [PATCH 2/6] 6loWPAN: Add network IOCTL support to set the node address --- include/netutils/netlib.h | 6 ++ netutils/netlib/Makefile | 8 +- netutils/netlib/netlib_setmacaddr.c | 3 - netutils/netlib/netlib_setnodeaddr.c | 107 +++++++++++++++++++++++++++ nshlib/nsh_netinit.c | 50 ++++++++++++- 5 files changed, 165 insertions(+), 9 deletions(-) create mode 100644 netutils/netlib/netlib_setnodeaddr.c diff --git a/include/netutils/netlib.h b/include/netutils/netlib.h index 7a67282d7..697d973c2 100644 --- a/include/netutils/netlib.h +++ b/include/netutils/netlib.h @@ -114,6 +114,12 @@ int netlib_setmacaddr(FAR const char *ifname, FAR const uint8_t *macaddr); int netlib_getmacaddr(FAR const char *ifname, FAR uint8_t *macaddr); #endif +#ifdef CONFIG_NET_ETHERNET +/* Get IEEE802.15.4 MAC driver node address */ + +int netlib_setnodeaddr(FAR const char *ifname, FAR const uint8_t *nodeaddr); +#endif + /* IP address support */ #ifdef CONFIG_NET_IPv4 diff --git a/netutils/netlib/Makefile b/netutils/netlib/Makefile index b17c97f59..35030cab5 100644 --- a/netutils/netlib/Makefile +++ b/netutils/netlib/Makefile @@ -37,7 +37,7 @@ -include $(TOPDIR)/Make.defs include $(APPDIR)/Make.defs -# UIP Library +# Network Library ASRCS = CSRCS = netlib_ipv4addrconv.c netlib_ethaddrconv.c netlib_parsehttpurl.c @@ -80,12 +80,16 @@ ifeq ($(CONFIG_NETDEV_WIRELESS_IOCTL),y) CSRCS += netlib_getessid.c netlib_setessid.c endif -# No MAC address support for SLIP (Ethernet only) +# MAC address support(Ethernet and 6loWPAN only) ifeq ($(CONFIG_NET_ETHERNET),y) CSRCS += netlib_setmacaddr.c netlib_getmacaddr.c endif +ifeq ($(CONFIG_NET_6LOWPAN),y) +CSRCS += netlib_setnodeaddr.c +endif + # IGMP support ifeq ($(CONFIG_NET_IGMP),y) diff --git a/netutils/netlib/netlib_setmacaddr.c b/netutils/netlib/netlib_setmacaddr.c index 8847ff6f8..d404c1af1 100644 --- a/netutils/netlib/netlib_setmacaddr.c +++ b/netutils/netlib/netlib_setmacaddr.c @@ -52,9 +52,6 @@ #include "netutils/netlib.h" -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ diff --git a/netutils/netlib/netlib_setnodeaddr.c b/netutils/netlib/netlib_setnodeaddr.c new file mode 100644 index 000000000..942186070 --- /dev/null +++ b/netutils/netlib/netlib_setnodeaddr.c @@ -0,0 +1,107 @@ +/**************************************************************************** + * netutils/netlib/netlib_setnodeaddr.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "netutils/netlib.h" + +#if defined(CONFIG_NET_6LOWPAN) && CONFIG_NSOCKET_DESCRIPTORS > 0 + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: netlib_setnodeaddr + * + * Description: + * Set the 6loWPAN IEEE802.15.4 MAC network driver node address + * + * Parameters: + * ifname The name of the interface to use + * nodeaddr Node address to set, size must be CONFIG_NET_6LOWPAN_RIMEADDR_SIZE + * + * Return: + * 0 on success; -1 on failure + * + ****************************************************************************/ + +int netlib_setnodeaddr(FAR const char *ifname, FAR const uint8_t *nodeaddr) +{ + int ret = ERROR; + + if (ifname && nodeaddr) + { + /* Get a socket (only so that we get access to the INET subsystem) */ + + int sockfd = socket(PF_INET6, NETLIB_SOCK_IOCTL, 0); + if (sockfd >= 0) + { + struct ifreq req; + + /* Put the driver name into the request */ + + strncpy(req.ifr_name, ifname, IFNAMSIZ); + + /* Put the new MAC address into the request */ + + req.ifr_hwaddr.sa_family = AF_INET6; + memcpy(&req.ifr_hwaddr.sa_data, nodeaddr, CONFIG_NET_6LOWPAN_RIMEADDR_SIZE); + + /* Perform the ioctl to set the MAC address */ + + ret = ioctl(sockfd, SIOCSIFHWADDR, (unsigned long)&req); + close(sockfd); + } + } + + return ret; +} + +#endif /* CONFIG_NET_6LOWPAN && CONFIG_NSOCKET_DESCRIPTORS */ diff --git a/nshlib/nsh_netinit.c b/nshlib/nsh_netinit.c index 8ee0958ef..38c862a30 100644 --- a/nshlib/nsh_netinit.c +++ b/nshlib/nsh_netinit.c @@ -84,6 +84,20 @@ * Pre-processor Definitions ****************************************************************************/ +/* Only Ethernet and 6loWPAN have MAC layer addresses */ + +#undef HAVE_MAC +#if defined(CONFIG_NET_ETHERNET) || defined(CONFIG_NET_6LOWPAN) +# define HAVE_MAC 1 +# if defined(CONFIG_NET_6LOWPAN) +# if (CONFIG_NET_6LOWPAN_RIMEADDR_SIZE == 2) && CONFIG_NSH_MACADDR > 0xffff +# error Invalid 6loWPAN node address for SIZE == 2 +# elif (CONFIG_NET_6LOWPAN_RIMEADDR_SIZE == 8) && CONFIG_NSH_MACADDR > 0xffffffffffffffffull +# error Invalid 6loWPAN node address for SIZE == 8 +# endif +# endif +#endif + #if defined(CONFIG_NSH_DRIPADDR) && !defined(CONFIG_NSH_DNSIPADDR) # define CONFIG_NSH_DNSIPADDR CONFIG_NSH_DRIPADDR #endif @@ -226,19 +240,25 @@ static void nsh_netinit_configure(void) #ifdef CONFIG_NET_IPv4 struct in_addr addr; #endif + #if defined(CONFIG_NSH_DHCPC) FAR void *handle; #endif -#if (defined(CONFIG_NSH_DHCPC) || defined(CONFIG_NSH_NOMAC)) && \ - defined(CONFIG_NET_ETHERNET) + +#if (defined(CONFIG_NSH_DHCPC) || defined(CONFIG_NSH_NOMAC)) && defined(HAVE_MAC) +#if defined(CONFIG_NET_ETHERNET) uint8_t mac[IFHWADDRLEN]; +#elif defined(CONFIG_NET_6LOWPAN) + uint8_t nodeaddr[CONFIG_NET_6LOWPAN_RIMEADDR_SIZE]; +#endif #endif ninfo("Entry\n"); /* Many embedded network interfaces must have a software assigned MAC */ -#if defined(CONFIG_NSH_NOMAC) && defined(CONFIG_NET_ETHERNET) +#if defined(CONFIG_NSH_NOMAC) && defined(HAVE_MAC) +#if defined(CONFIG_NET_ETHERNET) /* Use the configured, fixed MAC address */ mac[0] = (CONFIG_NSH_MACADDR >> (8 * 5)) & 0xff; @@ -252,7 +272,29 @@ static void nsh_netinit_configure(void) netlib_setmacaddr(NET_DEVNAME, mac); -#endif /* CONFIG_NSH_NOMAC && CONFIG_NET_ETHERNET */ +#elif defined(CONFIG_NET_6LOWPAN) + /* Use the configured, fixed MAC address */ + +#if CONFIG_NET_6LOWPAN_RIMEADDR_SIZE == 2 + nodeaddr[0] = (CONFIG_NSH_MACADDR >> (8 * 1)) & 0xff; + nodeaddr[1] = (CONFIG_NSH_MACADDR >> (8 * 0)) & 0xff; +#elif CONFIG_NET_6LOWPAN_RIMEADDR_SIZE == 8 + nodeaddr[0] = (CONFIG_NSH_MACADDR >> (8 * 7)) & 0xff; + nodeaddr[1] = (CONFIG_NSH_MACADDR >> (8 * 6)) & 0xff; + nodeaddr[2] = (CONFIG_NSH_MACADDR >> (8 * 5)) & 0xff; + nodeaddr[3] = (CONFIG_NSH_MACADDR >> (8 * 4)) & 0xff; + nodeaddr[4] = (CONFIG_NSH_MACADDR >> (8 * 3)) & 0xff; + nodeaddr[5] = (CONFIG_NSH_MACADDR >> (8 * 2)) & 0xff; + nodeaddr[6] = (CONFIG_NSH_MACADDR >> (8 * 1)) & 0xff; + nodeaddr[7] = (CONFIG_NSH_MACADDR >> (8 * 0)) & 0xff; +#endif + + /* Set the 6loWPAN node address */ + + netlib_setnodeaddr(NET_DEVNAME, nodeaddr); + +#endif /* CONFIG_NET_ETHERNET */ +#endif /* CONFIG_NSH_NOMAC && HAVE_MAC */ #ifdef CONFIG_NET_IPv4 /* Set up our host address */ From 1fde89e2d94929a210f9bdc4f66afcf71717a561 Mon Sep 17 00:00:00 2001 From: Mark Schulte Date: Fri, 7 Apr 2017 07:23:14 -0600 Subject: [PATCH 3/6] examples/ostest: Add tests for pthread_rwlock. Adding tests to be used to verify the pthread_rwlock lock works --- examples/ostest/Makefile | 4 + examples/ostest/ostest.h | 4 + examples/ostest/ostest_main.c | 8 + examples/ostest/pthread_rwlock.c | 250 +++++++++++++++++++++++++++++++ 4 files changed, 266 insertions(+) create mode 100644 examples/ostest/pthread_rwlock.c diff --git a/examples/ostest/Makefile b/examples/ostest/Makefile index 99d4d3adf..6d7df2923 100644 --- a/examples/ostest/Makefile +++ b/examples/ostest/Makefile @@ -93,6 +93,10 @@ CSRCS += sporadic.c endif endif # CONFIG_DISABLE_PTHREAD +ifeq ($(CONFIG_PTHREAD_RWLOCK),y) +CSRCS += pthread_rwlock.c +endif + ifneq ($(CONFIG_DISABLE_MQUEUE),y) ifneq ($(CONFIG_DISABLE_PTHREAD),y) CSRCS += mqueue.c timedmqueue.c diff --git a/examples/ostest/ostest.h b/examples/ostest/ostest.h index 17ee5b85d..7cd9458ed 100644 --- a/examples/ostest/ostest.h +++ b/examples/ostest/ostest.h @@ -216,6 +216,10 @@ void sporadic_test(void); void tls_test(void); +/* pthread_rwlock.c ****************************************************************/ + +void pthread_rwlock_test(void); + /* barrier.c ****************************************************************/ void barrier_test(void); diff --git a/examples/ostest/ostest_main.c b/examples/ostest/ostest_main.c index 7d1734c97..dda6579d7 100644 --- a/examples/ostest/ostest_main.c +++ b/examples/ostest/ostest_main.c @@ -426,6 +426,14 @@ static int user_main(int argc, char *argv[]) #endif #endif +#ifdef CONFIG_PTHREAD_RWLOCK + /* Verify pthreads and pthread mutex */ + + printf("\nuser_main: pthread_rwlock test\n"); + pthread_rwlock_test(); + check_test_memory_usage(); +#endif /* CONFIG_PTHREAD_RWLOCK */ + #ifndef CONFIG_DISABLE_PTHREAD /* Verify pthreads and condition variable timed waits */ diff --git a/examples/ostest/pthread_rwlock.c b/examples/ostest/pthread_rwlock.c new file mode 100644 index 000000000..9d3f7216d --- /dev/null +++ b/examples/ostest/pthread_rwlock.c @@ -0,0 +1,250 @@ +/**************************************************************************** + * apps/examples/pthread_rwlock.c + * + * Copyright (C) 2017 Mark Schulte. All rights reserved. + * Author: Mark Schulte + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct race_cond_s +{ + sem_t * sem1; + sem_t * sem2; + pthread_rwlock_t *rw_lock; +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static FAR void *race_cond_thread1(FAR void *data) +{ + FAR struct race_cond_s *rc = (FAR struct race_cond_s *) data; + int status; + + /* Runs 1st */ + + status = pthread_rwlock_wrlock(rc->rw_lock); + if (status != 0) + { + printf("pthread_rwlock: Failed to lock for writing\n"); + } + + sem_post(rc->sem2); + sem_wait(rc->sem1); + + /* Context Switch -> Runs 3rd */ + + status = pthread_rwlock_unlock(rc->rw_lock); + if (status != 0) + { + printf("pthread_rwlock: Failed to unlock lock held for writing\n"); + } + + status = pthread_rwlock_rdlock(rc->rw_lock); + if (status != 0) + { + printf("pthread_rwlock: Failed to open rwlock for reading. Status: %d\n", status); + } + + sem_wait(rc->sem1); + + /* Context Switch - Runs 5th */ + + status = pthread_rwlock_unlock(rc->rw_lock); + if (status != 0) + { + printf("pthread_rwlock: Failed to unlock lock held for writing\n"); + } + + return NULL; +} + +static FAR void *race_cond_thread2(FAR void *data) +{ + FAR struct race_cond_s *rc = (FAR struct race_cond_s *) data; + int status; + + status = sem_wait(rc->sem2); + + /* Runs 2nd */ + + if (status != 0) + { + printf("pthread_rwlock: Failed to wait on semaphore. Status: %d\n", status); + } + + status = pthread_rwlock_tryrdlock(rc->rw_lock); + if (status != EBUSY) + { + printf("pthread_rwlock: Opened rw_lock for rd when locked for writing: %d\n", status); + } + + status = pthread_rwlock_trywrlock(rc->rw_lock); + if (status != EBUSY) + { + printf("pthread_rwlock: Opened rw_lock for wr when locked for writing: %d\n", status); + } + sem_post(rc->sem1); + status = pthread_rwlock_rdlock(rc->rw_lock); + + /* Context - Switch Runs 4th */ + + if (status != 0) + { + printf("pthread_rwlock: Failed to open rwlock for reading. Status: %d\n", status); + } + + status = pthread_rwlock_unlock(rc->rw_lock); + if (status != 0) + { + printf("pthread_rwlock: Failed to unlock lock held for writing\n"); + } + + sem_post(rc->sem1); + return NULL; +} + +static void test_two_threads(void) +{ + pthread_rwlock_t rw_lock; + struct race_cond_s rc; + pthread_t thread1; + pthread_t thread2; + sem_t sem1; + sem_t sem2; + int status; + + status = pthread_rwlock_init(&rw_lock, NULL); + if (status != 0) + { + printf("pthread_rwlock: ERROR pthread_rwlock_init failed, status=%d\n", status); + } + + status = sem_init(&sem1, 0, 0); + if (status != 0) + { + printf("pthread_rwlock: ERROR sem_init failed, status=%d\n", status); + } + + status = sem_init(&sem2, 0, 0); + if (status != 0) + { + printf("pthread_rwlock: ERROR sem_init failed, status=%d\n", status); + } + + rc.sem1 = &sem1; + rc.sem2 = &sem2; + rc.rw_lock = &rw_lock; + + status = pthread_create(&thread1, NULL, race_cond_thread1, &rc); + status = pthread_create(&thread2, NULL, race_cond_thread2, &rc); + (void) pthread_join(thread1, NULL); + (void) pthread_join(thread2, NULL); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void pthread_rwlock_test(void) +{ + pthread_rwlock_t rw_lock; + int status; + + printf("pthread_rwlock: Initializing rwlock\n"); + + status = pthread_rwlock_init(&rw_lock, NULL); + if (status != 0) + { + printf("pthread_rwlock: " + "ERROR pthread_rwlock_init failed, status=%d\n", + status); + } + + status = pthread_rwlock_trywrlock(&rw_lock); + if (status != 0) + { + printf("pthread_rwlock: " + "ERROR pthread_rwlock_trywrlock failed, status=%d\n", + status); + } + + status = pthread_rwlock_unlock(&rw_lock); + if (status != 0) + { + printf("pthread_rwlock: " + "ERROR pthread_rwlock_unlock failed, status=%d\n", + status); + } + + status = pthread_rwlock_trywrlock(&rw_lock); + if (status != 0) + { + printf("pthread_rwlock: " + "ERROR pthread_rwlock_trywrlock failed, status=%d\n", + status); + } + + status = pthread_rwlock_trywrlock(&rw_lock); + if (status != EBUSY) + { + printf("pthread_rwlock: ""ERROR able to acquire to write locks\n"); + } + + status = pthread_rwlock_tryrdlock(&rw_lock); + if (status != EBUSY) + { + printf("pthread_rwlock: " + "ERROR able to acquire read lock when read lock already acquired\n"); + } + + status = pthread_rwlock_unlock(&rw_lock); + if (status != 0) + { + printf("pthread_rwlock: " + "ERROR pthread_rwlock_unlock failed, status=%d\n", + status); + } + + test_two_threads(); +} From 4c56a28016c92b0e9996a91a391be204e5582ef4 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 7 Apr 2017 07:24:09 -0600 Subject: [PATCH 4/6] 6loWPAN: Fix some conditional compilation --- include/netutils/netlib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/netutils/netlib.h b/include/netutils/netlib.h index 697d973c2..f096e7baf 100644 --- a/include/netutils/netlib.h +++ b/include/netutils/netlib.h @@ -114,7 +114,7 @@ int netlib_setmacaddr(FAR const char *ifname, FAR const uint8_t *macaddr); int netlib_getmacaddr(FAR const char *ifname, FAR uint8_t *macaddr); #endif -#ifdef CONFIG_NET_ETHERNET +#ifdef CONFIG_NET_6LOWPAN /* Get IEEE802.15.4 MAC driver node address */ int netlib_setnodeaddr(FAR const char *ifname, FAR const uint8_t *nodeaddr); From acb60779883f4f11280985a8cd286a27d4bee922 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 7 Apr 2017 07:30:52 -0600 Subject: [PATCH 5/6] Remove CONFIG_PTHREAD_RWLOCK. Rwlock interfaces built unconditionally. --- examples/ostest/Makefile | 5 +---- examples/ostest/ostest_main.c | 6 ++---- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/examples/ostest/Makefile b/examples/ostest/Makefile index 6d7df2923..5006623fd 100644 --- a/examples/ostest/Makefile +++ b/examples/ostest/Makefile @@ -71,6 +71,7 @@ endif ifneq ($(CONFIG_DISABLE_PTHREAD),y) CSRCS += cancel.c cond.c mutex.c sem.c semtimed.c barrier.c timedwait.c +CSRCS += pthread_rwlock.c ifneq ($(CONFIG_PTHREAD_MUTEX_UNSAFE),y) CSRCS += robust.c @@ -93,10 +94,6 @@ CSRCS += sporadic.c endif endif # CONFIG_DISABLE_PTHREAD -ifeq ($(CONFIG_PTHREAD_RWLOCK),y) -CSRCS += pthread_rwlock.c -endif - ifneq ($(CONFIG_DISABLE_MQUEUE),y) ifneq ($(CONFIG_DISABLE_PTHREAD),y) CSRCS += mqueue.c timedmqueue.c diff --git a/examples/ostest/ostest_main.c b/examples/ostest/ostest_main.c index dda6579d7..d623d8482 100644 --- a/examples/ostest/ostest_main.c +++ b/examples/ostest/ostest_main.c @@ -424,15 +424,13 @@ static int user_main(int argc, char *argv[]) cond_test(); check_test_memory_usage(); #endif -#endif -#ifdef CONFIG_PTHREAD_RWLOCK - /* Verify pthreads and pthread mutex */ + /* Verify pthreads rwlock interfaces */ printf("\nuser_main: pthread_rwlock test\n"); pthread_rwlock_test(); check_test_memory_usage(); -#endif /* CONFIG_PTHREAD_RWLOCK */ +#endif /* !CONFIG_DISABLE_PTHREAD */ #ifndef CONFIG_DISABLE_PTHREAD /* Verify pthreads and condition variable timed waits */ From d7932d55dffb973d6f4ab81fc3c4a6a3e5dd15ea Mon Sep 17 00:00:00 2001 From: Mark Schulte Date: Fri, 7 Apr 2017 15:47:16 -0600 Subject: [PATCH 6/6] examples/ostest: pthread rwlock additional tests and bugfixes --- examples/ostest/pthread_rwlock.c | 197 +++++++++++++++++++++++++++++++ examples/ostest/roundrobin.c | 2 +- 2 files changed, 198 insertions(+), 1 deletion(-) diff --git a/examples/ostest/pthread_rwlock.c b/examples/ostest/pthread_rwlock.c index 9d3f7216d..a53242899 100644 --- a/examples/ostest/pthread_rwlock.c +++ b/examples/ostest/pthread_rwlock.c @@ -52,6 +52,11 @@ struct race_cond_s pthread_rwlock_t *rw_lock; }; +/**************************************************************************** + * Private Data + ****************************************************************************/ +static int g_race_cond_thread_pos; + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -63,6 +68,12 @@ static FAR void *race_cond_thread1(FAR void *data) /* Runs 1st */ + if (g_race_cond_thread_pos++ != 0) + { + printf("pthread_rwlock: Thread order unexpected. Expected 0, got %d", + g_race_cond_thread_pos); + } + status = pthread_rwlock_wrlock(rc->rw_lock); if (status != 0) { @@ -74,6 +85,12 @@ static FAR void *race_cond_thread1(FAR void *data) /* Context Switch -> Runs 3rd */ + if (g_race_cond_thread_pos++ != 2) + { + printf("pthread_rwlock: Thread order unexpected. Expected 2, got %d", + g_race_cond_thread_pos); + } + status = pthread_rwlock_unlock(rc->rw_lock); if (status != 0) { @@ -90,12 +107,41 @@ static FAR void *race_cond_thread1(FAR void *data) /* Context Switch - Runs 5th */ + if (g_race_cond_thread_pos++ != 4) + { + printf("pthread_rwlock: Thread order unexpected. Expected 4, got %d", + g_race_cond_thread_pos); + } + status = pthread_rwlock_unlock(rc->rw_lock); if (status != 0) { printf("pthread_rwlock: Failed to unlock lock held for writing\n"); } + status = pthread_rwlock_rdlock(rc->rw_lock); + if (status != 0) + { + printf("pthread_rwlock: Failed to open rwlock for reading. Status: %d\n", status); + } + + sem_post(rc->sem2); + sem_wait(rc->sem1); + + /* Context switch - Runs 7th */ + + if (g_race_cond_thread_pos++ != 6) + { + printf("pthread_rwlock: Thread order unexpected. Expected 6, got %d", + g_race_cond_thread_pos); + } + + status = pthread_rwlock_unlock(rc->rw_lock); + if (status != 0) + { + printf("pthread_rwlock: Failed to unlock lock held for reading. Status: %d\n", status); + } + return NULL; } @@ -113,6 +159,11 @@ static FAR void *race_cond_thread2(FAR void *data) printf("pthread_rwlock: Failed to wait on semaphore. Status: %d\n", status); } + if (g_race_cond_thread_pos++ != 1) + { + printf("pthread_rwlock: Thread order unexpected. Expected 1, got %d", g_race_cond_thread_pos); + } + status = pthread_rwlock_tryrdlock(rc->rw_lock); if (status != EBUSY) { @@ -134,6 +185,12 @@ static FAR void *race_cond_thread2(FAR void *data) printf("pthread_rwlock: Failed to open rwlock for reading. Status: %d\n", status); } + if (g_race_cond_thread_pos++ != 3) + { + printf("pthread_rwlock: Thread order unexpected. Expected 3, got %d", + g_race_cond_thread_pos); + } + status = pthread_rwlock_unlock(rc->rw_lock); if (status != 0) { @@ -141,6 +198,38 @@ static FAR void *race_cond_thread2(FAR void *data) } sem_post(rc->sem1); + sem_wait(rc->sem2); + + /* Context switch Runs 6th */ + + if (g_race_cond_thread_pos++ != 5) + { + printf("pthread_rwlock: Thread order unexpected. Expected 5, got %d", + g_race_cond_thread_pos); + } + + sem_post(rc->sem1); + status = pthread_rwlock_wrlock(rc->rw_lock); + + /* Context switch runs 8th */ + + if (status != 0) + { + printf("pthread_rwlock: Failed to open rwlock for reading. Status: %d\n", status); + } + + if (g_race_cond_thread_pos++ != 7) + { + printf("pthread_rwlock: Thread order unexpected. Expected 7, got %d", + g_race_cond_thread_pos); + } + + status = pthread_rwlock_unlock(rc->rw_lock); + if (status != 0) + { + printf("pthread_rwlock: Failed to unlock lock held for writing. Status: %d\n", status); + } + return NULL; } @@ -176,12 +265,118 @@ static void test_two_threads(void) rc.sem2 = &sem2; rc.rw_lock = &rw_lock; + g_race_cond_thread_pos = 0; status = pthread_create(&thread1, NULL, race_cond_thread1, &rc); status = pthread_create(&thread2, NULL, race_cond_thread2, &rc); (void) pthread_join(thread1, NULL); (void) pthread_join(thread2, NULL); } +static void * timeout_thread1(FAR void * data) +{ + FAR struct race_cond_s * rc = (FAR struct race_cond_s *) data; + int status; + + status = pthread_rwlock_wrlock(rc->rw_lock); + if (status != 0) + { + printf("pthread_rwlock: Failed to acquire rw_lock. Status: %d\n", status); + } + + sem_wait(rc->sem1); + + status = pthread_rwlock_unlock(rc->rw_lock); + if (status != 0) + { + printf("pthread_rwlock: Failed to unlock rw_lock. Status: %d\n", status); + } + + return NULL; +} + +static void * timeout_thread2(FAR void * data) +{ + FAR struct race_cond_s * rc = (FAR struct race_cond_s *) data; + struct timespec time; + int status; + + status = clock_gettime(CLOCK_REALTIME, &time); + time.tv_sec += 2; + + status = pthread_rwlock_timedwrlock(rc->rw_lock, &time); + if (status != ETIMEDOUT) + { + printf("pthread_rwlock: Failed to properly timeout write lock\n"); + } + + status = clock_gettime(CLOCK_REALTIME, &time); + time.tv_sec += 2; + + status = pthread_rwlock_timedrdlock(rc->rw_lock, &time); + if (status != ETIMEDOUT) + { + printf("pthread_rwlock: Failed to properly timeout rd lock\n"); + } + + status = clock_gettime(CLOCK_REALTIME, &time); + time.tv_sec += 2; + + sem_post(rc->sem1); + status = pthread_rwlock_timedrdlock(rc->rw_lock, &time); + if (status != 0) + { + printf("pthread_rwlock: Failed to properly acquire rdlock\n"); + } + + status = pthread_rwlock_unlock(rc->rw_lock); + if (status != 0) + { + printf("pthread_rwlock: Failed to release rdlock\n"); + } + + return NULL; +} + +static void test_timeout(void) +{ + pthread_rwlock_t rw_lock; + struct race_cond_s rc; + pthread_t thread1; + pthread_t thread2; + int status; + sem_t sem1; + sem_t sem2; + + status = pthread_rwlock_init(&rw_lock, NULL); + if (status != 0) + { + printf("pthread_rwlock: ERROR pthread_rwlock_init failed, status=%d\n", + status); + } + + status = sem_init(&sem1, 0, 0); + if (status != 0) + { + printf("pthread_rwlock: ERROR sem_init failed, status=%d\n", status); + } + + status = sem_init(&sem2, 0, 0); + if (status != 0) + { + printf("pthread_rwlock: ERROR sem_init failed, status=%d\n", status); + } + + rc.sem1 = &sem1; + rc.sem2 = &sem2; + rc.rw_lock = &rw_lock; + + status = pthread_create(&thread1, NULL, timeout_thread1, &rc); + status = pthread_create(&thread2, NULL, timeout_thread2, &rc); + + (void) pthread_join(thread1, NULL); + (void) pthread_join(thread2, NULL); +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -247,4 +442,6 @@ void pthread_rwlock_test(void) } test_two_threads(); + + test_timeout(); } diff --git a/examples/ostest/roundrobin.c b/examples/ostest/roundrobin.c index 5a807cf5f..4bd2d9ed4 100644 --- a/examples/ostest/roundrobin.c +++ b/examples/ostest/roundrobin.c @@ -127,7 +127,7 @@ static void get_primes(int *count, int *last) static FAR void *get_primes_thread(FAR void *parameter) { - int id = (int)parameter; + int id = (int)((intptr_t)parameter); int count; int last; int i;