Line data Source code
1 : #define _GNU_SOURCE 2 : #include <errno.h> 3 : #include <sched.h> 4 : 5 : #include <unistd.h> 6 : #include <fcntl.h> 7 : #include <stdio.h> 8 : #include <stdlib.h> 9 : #include <ctype.h> 10 : 11 : #include "fd_tile_private.h" 12 : 13 : int 14 : fd_cpuset_getaffinity( ulong pid, 15 6317 : fd_cpuset_t * mask ) { 16 6317 : # if defined(__linux__) 17 6317 : return sched_getaffinity( (int)pid, fd_cpuset_word_cnt<<3, (cpu_set_t *)fd_type_pun( mask ) ); 18 : # else 19 : (void)pid; (void)mask; 20 : errno = ENOTSUP; 21 : return -1; 22 : # endif 23 6317 : } 24 : 25 : int 26 : fd_cpuset_setaffinity( ulong pid, 27 12 : fd_cpuset_t const * mask ) { 28 12 : # if defined(__linux__) 29 12 : return sched_setaffinity( (int)pid, fd_cpuset_word_cnt<<3, (cpu_set_t const *)fd_type_pun_const( mask ) ); 30 : # else 31 : (void)pid; (void)mask; 32 : errno = ENOTSUP; 33 : return -1; 34 : # endif 35 12 : } 36 : 37 : ulong 38 : fd_tile_private_sibling_parse( char const * list, 39 867 : ulong cpu_idx ) { 40 867 : ulong cnt = 0UL; 41 867 : ulong other = ULONG_MAX; 42 867 : int found = 0; 43 867 : char const * p = list; 44 1704 : for(;;) { 45 1704 : if( FD_UNLIKELY( !fd_isdigit( (int)p[0] ) ) ) return ULONG_MAX-1UL; 46 1695 : char * end; 47 1695 : ulong lo = strtoul( p, &end, 10 ); 48 1695 : ulong hi = lo; 49 1695 : p = end; 50 1695 : if( p[0]=='-' ) { 51 18 : p++; 52 18 : if( FD_UNLIKELY( !fd_isdigit( (int)p[0] ) ) ) return ULONG_MAX-1UL; 53 15 : hi = strtoul( p, &end, 10 ); 54 15 : p = end; 55 15 : } 56 1692 : if( FD_UNLIKELY( hi<lo || hi>=FD_TILE_MAX ) ) return ULONG_MAX-1UL; 57 1689 : cnt += hi-lo+1UL; 58 1689 : if( cpu_idx>=lo && cpu_idx<=hi ) found = 1; 59 1689 : if( lo!=cpu_idx ) other = lo; 60 843 : else if( hi!=cpu_idx ) other = hi; 61 1689 : if( p[0]!=',' ) break; 62 837 : p++; 63 837 : } 64 852 : if( FD_UNLIKELY( !( p[0]=='\0' || ( p[0]=='\n' && p[1]=='\0' ) ) || !found || cnt>2UL ) ) return ULONG_MAX-1UL; 65 837 : return cnt==2UL ? other : ULONG_MAX; 66 852 : } 67 : 68 : ulong 69 810 : fd_tile_private_sibling_idx( ulong cpu_idx ) { 70 810 : # if defined(__linux__) 71 810 : char path[ PATH_MAX ]; 72 810 : FD_TEST( fd_cstr_printf_check( path, PATH_MAX, NULL, "/sys/devices/system/cpu/cpu%lu/topology/thread_siblings_list", cpu_idx ) ); 73 : 74 810 : int fd = open( path, O_RDONLY ); 75 810 : if( FD_UNLIKELY( -1==fd ) ) FD_LOG_ERR(( "open( \"%s\" ) failed (%i-%s)", path, errno, fd_io_strerror( errno ) )); 76 : 77 810 : char line[ 1024 ] = {0}; 78 810 : long bytes_read = read( fd, line, sizeof( line ) ); 79 810 : if( FD_UNLIKELY( -1==bytes_read ) ) FD_LOG_ERR(( "read( \"%s\" ) failed (%i-%s)", path, errno, fd_io_strerror( errno ) )); 80 810 : else if ( FD_UNLIKELY( (ulong)bytes_read>=sizeof( line ) ) ) FD_LOG_ERR(( "read( \"%s\" ) failed: buffer too small", path )); 81 : 82 810 : if( FD_UNLIKELY( close( fd ) ) ) FD_LOG_ERR(( "close( \"%s\" ) failed (%i-%s)", path, errno, fd_io_strerror( errno ) )); 83 : 84 810 : ulong sibling = fd_tile_private_sibling_parse( line, cpu_idx ); 85 810 : if( FD_UNLIKELY( sibling==ULONG_MAX-1UL ) ) FD_LOG_ERR(( "failed to parse cpu siblings list of cpu%lu `%s`", cpu_idx, line )); 86 810 : return sibling; 87 : # else 88 : (void)cpu_idx; 89 : return ULONG_MAX; 90 : # endif 91 810 : }