Val _lib7_Sock_inetany (Task* task, Val arg) { //================== // // Mythryl type: Int -> Internet_Address // // Make an INET_ANY INET socket address, with the given port ID. // // This fn gets bound as inet_any in: // // src/lib/std/src/socket/internet-socket.pkg // ENTER_MYTHRYL_CALLABLE_C_FN("_lib7_Sock_inetany"); struct sockaddr_in addr; memset( &addr, 0, sizeof(struct sockaddr_in) ); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl( INADDR_ANY ); addr.sin_port = htons( TAGGED_INT_TO_C_INT( arg ) ); // Last use of 'arg'. Val data = make_biwordslots_vector_sized_in_bytes__may_heapclean( task, &addr, sizeof(struct sockaddr_in), NULL ); return make_vector_header(task, UNT8_RO_VECTOR_TAGWORD, data, sizeof(struct sockaddr_in) ); }
Val _lib7_Sock_getATMARK (Task* task, Val arg) { //==================== // // Mythryl type: Socket_Fd -> Int // // This fn gets bound as get_atmark' in: // // src/lib/std/src/socket/socket-guts.pkg // ENTER_MYTHRYL_CALLABLE_C_FN(__func__); int device = TAGGED_INT_TO_C_INT( arg ); // Last use of 'arg'. RELEASE_MYTHRYL_HEAP( task->hostthread, __func__, NULL ); // int n; int status = ioctl (device, SIOCATMARK, (char*) &n ); // RECOVER_MYTHRYL_HEAP( task->hostthread, __func__ ); if (status < 0) return RAISE_SYSERR__MAY_HEAPCLEAN(task, status, NULL); EXIT_MYTHRYL_CALLABLE_C_FN(__func__); return n ? HEAP_TRUE : HEAP_FALSE; }
Val _lib7_netdb_get_protocol_by_number (Task* task, Val arg) { //================================== // // Mythryl type: Int -> Null_Or( (String, List(String), Int) ) // // This fn gets bound as get_prot_by_number' in: // // src/lib/std/src/socket/net-protocol-db.pkg ENTER_MYTHRYL_CALLABLE_C_FN(__func__); int number = TAGGED_INT_TO_C_INT( arg ); // Last use of 'arg'. RELEASE_MYTHRYL_HEAP( task->hostthread, __func__, NULL ); // struct protoent* pentry = getprotobynumber( number ); // RECOVER_MYTHRYL_HEAP( task->hostthread, __func__ ); if (pentry == NULL) return OPTION_NULL; Val name = make_ascii_string_from_c_string__may_heapclean (task, pentry->p_name, NULL ); Roots roots1 = { &name, NULL }; Val aliases = make_ascii_strings_from_vector_of_c_strings__may_heapclean(task, pentry->p_aliases, &roots1 ); Val result = make_three_slot_record( task, name, aliases, TAGGED_INT_FROM_C_INT(pentry->p_proto) ); result = OPTION_THE( task, result ); EXIT_MYTHRYL_CALLABLE_C_FN(__func__); return result; }
Val _lib7_P_IO_fsync (Task* task, Val arg) { //================ // // Mythryl type: Sy_Int -> Void // // Synchronize a file's in-core state with storage // // This fn gets bound as fsync' in: // // src/lib/std/src/posix-1003.1b/posix-io.pkg // src/lib/std/src/posix-1003.1b/posix-io-64.pkg ENTER_MYTHRYL_CALLABLE_C_FN("_lib7_P_IO_fsync"); int status; int fd = TAGGED_INT_TO_C_INT(arg); RELEASE_MYTHRYL_HEAP( task->pthread, "_lib7_P_IO_fsync", NULL ); // status = fsync(fd); // RECOVER_MYTHRYL_HEAP( task->pthread, "_lib7_P_IO_fsync" ); RETURN_VOID_EXCEPT_RAISE_SYSERR_ON_NEGATIVE_STATUS__MAY_HEAPCLEAN(task, status, NULL); }
Val _lib7_Sock_getpeername (Task* task, Val arg) { //====================== // // Mythryl type: Socket -> (Address_Family, Address) // // This function gets bound as get_peer_name' in: // // src/lib/std/src/socket/socket-guts.pkg ENTER_MYTHRYL_CALLABLE_C_FN(__func__); char addr[ MAX_SOCK_ADDR_BYTESIZE ]; socklen_t address_len = MAX_SOCK_ADDR_BYTESIZE; int sockfd = TAGGED_INT_TO_C_INT( arg ); // Last use of 'arg'. RELEASE_MYTHRYL_HEAP( task->hostthread, __func__, NULL ); // int status = getpeername (sockfd, (struct sockaddr *)addr, &address_len); // RECOVER_MYTHRYL_HEAP( task->hostthread, __func__ ); if (status < 0) return RAISE_SYSERR__MAY_HEAPCLEAN(task, status, NULL); Val cdata = make_biwordslots_vector_sized_in_bytes__may_heapclean( task, addr, address_len, NULL ); Val result = make_vector_header(task, UNT8_RO_VECTOR_TAGWORD, cdata, address_len); EXIT_MYTHRYL_CALLABLE_C_FN(__func__); return result; }
Val _lib7_P_TTY_tcgetattr (Task* task, Val arg) { //===================== // // Mythryl type: Int -> (Unt, Unt, Unt, Unt, String, Unt, Unt) // // Get parameters associated with tty. // // NOTE: the calls to cfget[io] speed by making the code more OS-dependent // and using the package of struct termios. // // This fn gets bound as tcgetattr in: // // src/lib/std/src/psx/posix-tty.pkg ENTER_MYTHRYL_CALLABLE_C_FN(__func__); int fd = TAGGED_INT_TO_C_INT( arg ); struct termios data; RELEASE_MYTHRYL_HEAP( task->hostthread, __func__, NULL); // int status = tcgetattr( fd, &data ); // RECOVER_MYTHRYL_HEAP( task->hostthread, __func__ ); if (status < 0) return RAISE_SYSERR__MAY_HEAPCLEAN(task, status, NULL); Val iflag = make_one_word_unt(task, data.c_iflag ); Roots roots1 = { &iflag, NULL }; Val oflag = make_one_word_unt(task, data.c_oflag ); Roots roots2 = { &oflag, &roots1 }; Val cflag = make_one_word_unt(task, data.c_cflag ); Roots roots3 = { &cflag, &roots2 }; Val lflag = make_one_word_unt(task, data.c_lflag ); Roots roots4 = { &lflag, &roots3 }; Val ispeed = make_one_word_unt(task, cfgetispeed (&data) ); Roots roots5 = { &ispeed, &roots4 }; Val ospeed = make_one_word_unt(task, cfgetospeed (&data) ); Roots roots6 = { &ospeed, &roots5 }; Val cc = allocate_nonempty_ascii_string__may_heapclean (task, NCCS, &roots6 ); memcpy( GET_VECTOR_DATACHUNK_AS( void*, cc ), data.c_cc, NCCS ); // Construct the result vector: // set_slot_in_nascent_heapchunk (task, 0, MAKE_TAGWORD(PAIRS_AND_RECORDS_BTAG, 7)); set_slot_in_nascent_heapchunk (task, 1, iflag); set_slot_in_nascent_heapchunk (task, 2, oflag); set_slot_in_nascent_heapchunk (task, 3, cflag); set_slot_in_nascent_heapchunk (task, 4, lflag); set_slot_in_nascent_heapchunk (task, 5, cc); set_slot_in_nascent_heapchunk (task, 6, ispeed); set_slot_in_nascent_heapchunk (task, 7, ospeed); Val result = commit_nascent_heapchunk (task, 7); EXIT_MYTHRYL_CALLABLE_C_FN(__func__); return result; }
Val _lib7_P_ProcEnv_isatty (Task* task, Val arg) { //====================== // // Mythryl type: Int -> Bool // // Is file descriptor associated with a terminal device? // // This fn gets bound as isatty' in: // // src/lib/std/src/posix-1003.1b/posix-id.pkg return (isatty(TAGGED_INT_TO_C_INT(arg)) ? HEAP_TRUE : HEAP_FALSE); }
Val _lib7_Sock_setprintiffd (Task* task, Val arg) { //======================= // // Mythryl type: Int -> Void // // This fn gets bound as set_printif_fd in: // // src/lib/std/src/socket/internet-socket.pkg ENTER_MYTHRYL_CALLABLE_C_FN("_lib7_Sock_setprintiffd"); int fd = TAGGED_INT_TO_C_INT(arg); log_if_fd = fd; return HEAP_VOID; }
Val get_or_set_socket_nodelay_option (Task* task, Val arg) { //================================ // // Mythryl type: (Int, Null_Or(Bool)) -> Bool // // NOTE: this is a TCP level option, so we cannot use the utility function. // // This fn gets bound as ctl_delay in: // // src/lib/std/src/socket/internet-socket.pkg ENTER_MYTHRYL_CALLABLE_C_FN("get_or_set_socket_nodelay_option"); int socket = GET_TUPLE_SLOT_AS_INT( arg, 0 ); Val ctl = GET_TUPLE_SLOT_AS_VAL( arg, 1 ); // Last use of 'arg'. // Bool flag; int status; if (ctl == OPTION_NULL) { // socklen_t opt_size = sizeof(int); RELEASE_MYTHRYL_HEAP( task->pthread, "get_or_set_socket_nodelay_option", NULL ); // status = getsockopt (socket, IPPROTO_TCP, TCP_NODELAY, (sockoptval_t)&flag, &opt_size); // RECOVER_MYTHRYL_HEAP( task->pthread, "get_or_set_socket_nodelay_option" ); ASSERT((status < 0) || (opt_size == sizeof(int))); } else { flag = (Bool) TAGGED_INT_TO_C_INT(OPTION_GET(ctl)); RELEASE_MYTHRYL_HEAP( task->pthread, "get_or_set_socket_nodelay_option", NULL ); // status = setsockopt (socket, IPPROTO_TCP, TCP_NODELAY, (sockoptval_t)&flag, sizeof(int)); // RECOVER_MYTHRYL_HEAP( task->pthread, "get_or_set_socket_nodelay_option" ); } if (status < 0) return RAISE_SYSERR__MAY_HEAPCLEAN(task, status, NULL); else return (flag ? HEAP_TRUE : HEAP_FALSE); }
Val _lib7_P_Error_errmsg (Task* task, Val arg) { //==================== // // Mythryl type: Int -> String // // Return the OS-dependent error message associated with error. // // This fn gets bound as errmsg in: // // src/lib/std/src/psx/posix-error.pkg ENTER_MYTHRYL_CALLABLE_C_FN(__func__); int errnum = TAGGED_INT_TO_C_INT( arg ); Val result; #if defined( HAS_STRERROR ) // char* msg = strerror( errnum ); // if (msg != 0) { // result = make_ascii_string_from_c_string__may_heapclean( task, msg, NULL ); // make_ascii_string_from_c_string__may_heapclean def in src/c/heapcleaner/make-strings-and-vectors-etc.c } else { char buf[64]; sprintf( buf, "<unknown error %d>", errnum); // XXX SUCKO FIXME should use a modern fn proof against buffer overrun. result = make_ascii_string_from_c_string__may_heapclean (task, buf, NULL ); } #else if (0 <= errnum && errnum < sys_nerr) { // result = make_ascii_string_from_c_string__may_heapclean (task, sys_errlist[errnum], NULL ); // } else { // char buf[64]; snprintf( buf, 64, "<unknown error %d>", errnum); result = make_ascii_string_from_c_string__may_heapclean (task, buf, NULL ); } #endif EXIT_MYTHRYL_CALLABLE_C_FN(__func__); return result; }
Val _lib7_NetDB_getrpcbynum (Task* task, Val arg) { //======================= // // Mythryl type: Int -> Null_Or( (String, List(String), Int) ) // // This fn is NOWHERE INVOKED. Nor listed in src/c/lib/socket/cfun-list.h Presumably should be either called or deleted: XXX BUGGO FIXME. struct rpcent* rentry = getrpcbynumber( TAGGED_INT_TO_C_INT( arg )); if (rentry == NULL) return OPTION_NULL; Val name = make_ascii_string_from_c_string( task, rentry->r_name ); Val aliases = make_ascii_strings_from_vector_of_c_strings( task, rentry->r_aliases); Val result; REC_ALLOC3( task, result, name, aliases, TAGGED_INT_FROM_C_INT(rentry->r_number)); OPTION_THE( task, result, result); return result; }
Val _lib7_Sock_accept (Task* task, Val arg) { //================= // // Mythryl type: Socket -> (Socket, Address) // // This fn gets bound as accept' in: // // src/lib/std/src/socket/socket-guts.pkg ENTER_MYTHRYL_CALLABLE_C_FN("_lib7_Sock_accept"); int socket = TAGGED_INT_TO_C_INT( arg ); // Last use of 'arg'. char address_buf[ MAX_SOCK_ADDR_BYTESIZE ]; socklen_t address_len = MAX_SOCK_ADDR_BYTESIZE; int new_socket; RELEASE_MYTHRYL_HEAP( task->pthread, "_lib7_Sock_accept", NULL ); // /* do { */ /* Backed out 2010-02-26 CrT: See discussion at bottom of src/c/lib/socket/connect.c */ new_socket = accept (socket, (struct sockaddr*) address_buf, &address_len); /* } while (new_socket < 0 && errno == EINTR); */ /* Restart if interrupted by a SIGALRM or SIGCHLD or whatever. */ // RECOVER_MYTHRYL_HEAP( task->pthread, "_lib7_Sock_accept" ); if (new_socket == -1) { // return RAISE_SYSERR__MAY_HEAPCLEAN( task, new_socket, NULL); // } else { // Val data = make_biwordslots_vector_sized_in_bytes__may_heapclean( task, address_buf, address_len, NULL ); Val address = make_vector_header( task, UNT8_RO_VECTOR_TAGWORD, data, address_len); return make_two_slot_record(task, TAGGED_INT_FROM_C_INT( new_socket ), address); } }
Val _lib7_P_IO_dup (Task* task, Val arg) { //============== // // Mythryl type: Int -> Int // // Duplicate an open file descriptor // // This fn gets bound as dup' in: // // src/lib/std/src/posix-1003.1b/posix-io.pkg // src/lib/std/src/posix-1003.1b/posix-io-64.pkg int fd0 = TAGGED_INT_TO_C_INT(arg); int fd1; /* do { */ // Backed out 2010-02-26 CrT: See discussion at bottom of src/c/lib/socket/connect.c fd1 = dup(fd0); /* } while (fd1 < 0 && errno == EINTR); */ // Restart if interrupted by a SIGALRM or SIGCHLD or whatever. CHECK_RETURN(task, fd1) }
Val _lib7_P_TTY_tcdrain (Task* task, Val arg) { //=================== // // Mythryl type: Int -> Void // // Wait for all output to be transmitted. // // This fn gets bound as tcdrain in: // // src/lib/std/src/posix-1003.1b/posix-tty.pkg ENTER_MYTHRYL_CALLABLE_C_FN("_lib7_P_TTY_tcdrain"); int fd = TAGGED_INT_TO_C_INT( arg ); RELEASE_MYTHRYL_HEAP( task->pthread, "_lib7_P_TTY_tcdrain", NULL ); // int status = tcdrain( fd ); // RECOVER_MYTHRYL_HEAP( task->pthread, "_lib7_P_TTY_tcdrain" ); RETURN_VOID_EXCEPT_RAISE_SYSERR_ON_NEGATIVE_STATUS__MAY_HEAPCLEAN(task, status, NULL); }
Val _lib7_P_TTY_tcgetpgrp (Task* task, Val arg) { //===================== // // Mythryl type: Int -> Int // // Get foreground process group id of tty. // // This fn gets bound as tcgetpgrp in: // // src/lib/std/src/posix-1003.1b/posix-tty.pkg ENTER_MYTHRYL_CALLABLE_C_FN("_lib7_P_TTY_tcgetpgrp"); int fd = TAGGED_INT_TO_C_INT( arg ); RELEASE_MYTHRYL_HEAP( task->pthread, "_lib7_P_TTY_tcgetpgrp", NULL ); // int result = tcgetpgrp( fd ); // RECOVER_MYTHRYL_HEAP( task->pthread, "_lib7_P_TTY_tcgetpgrp" ); return TAGGED_INT_FROM_C_INT( result ); }
Val _lib7_Sock_getNREAD (Task* task, Val arg) { //=================== // // Mythryl type: Socket -> Int // // This fn gets bound as get_nread' in: // // src/lib/std/src/socket/socket-guts.pkg ENTER_MYTHRYL_CALLABLE_C_FN("_lib7_Sock_getNREAD"); int device = TAGGED_INT_TO_C_INT( arg ); // Last use of 'arg'. RELEASE_MYTHRYL_HEAP( task->pthread, "_lib7_Sock_getNREAD", NULL ); // int n; int status = ioctl( device, FIONREAD, (char*) &n ); // RECOVER_MYTHRYL_HEAP( task->pthread, "_lib7_Sock_getNREAD" ); if (status < 0) return RAISE_SYSERR__MAY_HEAPCLEAN(task, status, NULL); return TAGGED_INT_FROM_C_INT( n ); }
Val _lib7_P_ProcEnv_ttyname (Task* task, Val arg) { //======================= // // Mythryl type: Int -> String // // Return terminal name associated with file descriptor, if any. // // This fn gets bound as ttyname' in: // // src/lib/std/src/psx/posix-id.pkg ENTER_MYTHRYL_CALLABLE_C_FN(__func__); RELEASE_MYTHRYL_HEAP( task->hostthread, __func__, NULL ); // char* name = ttyname(TAGGED_INT_TO_C_INT(arg)); // RECOVER_MYTHRYL_HEAP( task->hostthread, __func__ ); if (name == NULL) return RAISE_ERROR__MAY_HEAPCLEAN(task, "not a terminal device", NULL); // Val result = make_ascii_string_from_c_string__may_heapclean( task, name, NULL ); EXIT_MYTHRYL_CALLABLE_C_FN(__func__); return result; }
void partition_agegroup0_buffer_between_pthreads (Pthread *pthread_table[]) { // pthread_table is always pthread_table__global // =========================================== // // Outside of this file, this fn is called (only) from // // make_task in src/c/main/runtime-state.c // // Divide the agegroup0 buffer into smaller disjoint // buffers for use by the parallel pthreads. // // Typically at this point // // task0->heap->agegroup0_buffer_bytesize // // will at this point have been set to // // DEFAULT_AGEGROUP0_BUFFER_BYTESIZE // DEFAULT_AGEGROUP0_BUFFER_BYTESIZE is defined at 256K in src/c/h/runtime-configuration.h // * // MAX_PTHREADS // MAX_PTHREADS is defined as something like 8 or 16 in src/c/mythryl-config.h // // by the logic in // // src/c/heapcleaner/heapcleaner-initialization.c // int poll_freq = TAGGED_INT_TO_C_INT( DEREF( SOFTWARE_GENERATED_PERIODIC_EVENT_INTERVAL_REFCELL__GLOBAL ) ); Task* task; Task* task0 = pthread_table[ 0 ]->task; int per_thread_agegroup0_buffer_bytesize = task0->heap->agegroup0_buffer_bytesize / MAX_PTHREADS; Val* start_of_agegroup0_buffer_for_next_pthread = task0->heap->agegroup0_buffer; for (int pthread = 0; pthread < MAX_PTHREADS; pthread++) { // task = pthread_table[ pthread ]->task; #ifdef NEED_PTHREAD_SUPPORT_DEBUG debug_say ("pthread_table[%d]->task-> (heap_allocation_pointer %x/heap_allocation_limit %x) changed to ", pthread, task->heap_allocation_pointer, task->heap_allocation_limit); #endif task->heap = task0->heap; task->heap_allocation_pointer = start_of_agegroup0_buffer_for_next_pthread; task->real_heap_allocation_limit = HEAP_ALLOCATION_LIMIT_SIZE( start_of_agegroup0_buffer_for_next_pthread, per_thread_agegroup0_buffer_bytesize ); #if !NEED_PTHREAD_SUPPORT_FOR_SOFTWARE_GENERATED_PERIODIC_EVENTS // task->heap_allocation_limit = HEAP_ALLOCATION_LIMIT_SIZE( // HEAP_ALLOCATION_LIMIT_SIZE def in src/c/h/heap.h // // This macro basically just subtracts a MIN_FREE_BYTES_IN_AGEGROUP0_BUFFER safety margin from the actual buffer limit. start_of_agegroup0_buffer_for_next_pthread, per_thread_agegroup0_buffer_bytesize ); #else if (poll_freq <= 0) { // task->heap_allocation_limit = task->real_heap_allocation_limit; // } else { // // In order to generate software events at (approximately) // the desired frequency, we (may) here artificially decrease // the heaplimit pointer to trigger an early heapcleaner call, // at which point our logic will regain control. // #ifdef NEED_PTHREAD_SUPPORT_DEBUG debug_say ("(with poll_freq=%d) ", poll_freq); #endif task->heap_allocation_limit = start_of_agegroup0_buffer_for_next_pthread + poll_freq * PERIODIC_EVENT_TIME_GRANULARITY_IN_NEXTCODE_INSTRUCTIONS; task->heap_allocation_limit = (task->heap_allocation_limit > task->real_heap_allocation_limit) ? task->real_heap_allocation_limit : task->heap_allocation_limit; } #endif #ifdef NEED_PTHREAD_SUPPORT_DEBUG debug_say ("%x/%x\n",task->heap_allocation_pointer, task->heap_allocation_limit); #endif // Step over this pthread's buffer to // get start of next pthread's buffer: // start_of_agegroup0_buffer_for_next_pthread = (Val*) ( ((Punt) start_of_agegroup0_buffer_for_next_pthread) + per_thread_agegroup0_buffer_bytesize ); } // for (int pthread = 0; pthread < MAX_PTHREADS; pthread++) } // fun partition_agegroup0_buffer_between_pthreads
Val get_or_set_socket_linger_option (Task* task, Val arg) { //=============================== // // Mythryl type: (Socket_Fd, Null_Or(Null_Or(Int))) -> Null_Or(Int) // // Set/get the SO_LINGER option as follows: // NULL => get current setting // THE(NULL) => disable linger // THE(THE t) => enable linger with timeout t. // // This function gets bound as ctl_linger in: // // src/lib/std/src/socket/socket-guts.pkg // ENTER_MYTHRYL_CALLABLE_C_FN(__func__); int socket = GET_TUPLE_SLOT_AS_INT( arg, 0 ); Val ctl = GET_TUPLE_SLOT_AS_VAL( arg, 1 ); // Last use of 'arg'. struct linger optVal; int status; if (ctl == OPTION_NULL) { // socklen_t optSz = sizeof( struct linger ); RELEASE_MYTHRYL_HEAP( task->hostthread, __func__, NULL ); // status = getsockopt( socket, SOL_SOCKET, SO_LINGER, (sockoptval_t)&optVal, &optSz ); // RECOVER_MYTHRYL_HEAP( task->hostthread, __func__ ); ASSERT( status < 0 || optSz == sizeof( struct linger )); // } else { // ctl = OPTION_GET(ctl); if (ctl == OPTION_NULL) { optVal.l_onoff = 0; // Argument is THE(NULL); disable linger. } else { optVal.l_onoff = 1; // argument is THE t; enable linger. optVal.l_linger = TAGGED_INT_TO_C_INT(OPTION_GET(ctl)); } RELEASE_MYTHRYL_HEAP( task->hostthread, __func__, NULL ); // status = setsockopt (socket, SOL_SOCKET, SO_LINGER, (sockoptval_t)&optVal, sizeof(struct linger)); // RECOVER_MYTHRYL_HEAP( task->hostthread, __func__ ); } if (status < 0) return RAISE_SYSERR__MAY_HEAPCLEAN(task, status, NULL); if (optVal.l_onoff == 0) return OPTION_NULL; Val result = OPTION_THE( task, TAGGED_INT_FROM_C_INT( optVal.l_linger ) ); EXIT_MYTHRYL_CALLABLE_C_FN(__func__); return result; }