From 1d1451ccd2a6c0f0146ddee68f386061b69863c0 Mon Sep 17 00:00:00 2001 From: Takashi Yano Date: Thu, 12 Dec 2024 15:03:39 +0900 Subject: [PATCH 01/10] Cygwin: signal: Fix high load when retrying to process pending signal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The commit e10f822a2b39 has a problem that CPU load gets high if pending signal is not processed successfully for a long time. With this patch, wait_sig() calls Sleep(1), rather than yield(), if the pending signal has not been processed successfully for a predetermined time to prevent CPU from high load. Addresses: https://cygwin.com/pipermail/cygwin/2024-December/256884.html Fixes: e10f822a2b39 ("Cygwin: signal: Handle queued signal without explicit __SIGFLUSH") Reported-by: 凯夏 Reviewed-by: Corinna Vinschen Signed-off-by: Takashi Yano --- winsup/cygwin/sigproc.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index 59b4208a6..861a8c649 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -1345,6 +1345,12 @@ wait_sig (VOID *) hntdll = GetModuleHandle ("ntdll.dll"); + /* GetTickCount() here is enough because GetTickCount() - t0 does + not overflow until 49 days psss. Even if GetTickCount() overflows, + GetTickCount() - t0 returns correct value, since underflow in + unsigned wraps correctly. Pending a signal for more thtn 49 + days would be noncense. */ + DWORD t0 = GetTickCount (); for (;;) { DWORD nb; @@ -1354,7 +1360,7 @@ wait_sig (VOID *) else if (sigq.start.next && PeekNamedPipe (my_readsig, NULL, 0, NULL, &nb, NULL) && !nb) { - yield (); + Sleep (GetTickCount () - t0 > 10 ? 1 : 0); pack.si.si_signo = __SIGFLUSH; } else if (!ReadFile (my_readsig, &pack, sizeof (pack), &nb, NULL)) @@ -1364,6 +1370,8 @@ wait_sig (VOID *) system_printf ("garbled signal pipe data nb %u, sig %d", nb, pack.si.si_signo); continue; } + if (pack.si.si_signo != __SIGFLUSH) + t0 = GetTickCount (); sigq.retry = false; /* Don't process signals when we start exiting */ From 1f74e7e71a7c61541aebb54bba18e1c48fff1b74 Mon Sep 17 00:00:00 2001 From: Takashi Yano Date: Fri, 13 Dec 2024 20:56:52 +0900 Subject: [PATCH 02/10] Cygwin: signal: Fix typo in the comment added by previous commit Fixes: 1d1451ccd2a6 ("Cygwin: signal: Fix high load when retrying to process pending signal") Reported-by: Jon Turney Signed-off-by: Takashi Yano --- winsup/cygwin/sigproc.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index 861a8c649..ba7818a68 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -1348,8 +1348,8 @@ wait_sig (VOID *) /* GetTickCount() here is enough because GetTickCount() - t0 does not overflow until 49 days psss. Even if GetTickCount() overflows, GetTickCount() - t0 returns correct value, since underflow in - unsigned wraps correctly. Pending a signal for more thtn 49 - days would be noncense. */ + unsigned wraps correctly. Pending a signal for more than 49 + days makes no sense. */ DWORD t0 = GetTickCount (); for (;;) { From 8e53c587597a33fec5f41a540a9b1b20d53fb439 Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Thu, 12 Dec 2024 16:23:03 +0000 Subject: [PATCH 03/10] or1k: Fix compiler warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In my build the below are treated as error now and causing failures. I have described the fixes of each warning below. In newlib/libc/sys/or1k/mlock.c: CC libc/sys/or1k/libc_a-mlock.o newlib/libc/sys/or1k/mlock.c: In function ‘__malloc_lock’: newlib/libc/sys/or1k/mlock.c:56:19: warning: implicit declaration of function ‘or1k_critical_begin’ [-Wimplicit-function-declaration] 56 | restore = or1k_critical_begin(); | ^~~~~~~~~~~~~~~~~~~ newlib/libc/sys/or1k/mlock.c: In function ‘__malloc_unlock’: newlib/libc/sys/or1k/mlock.c:93:17: warning: implicit declaration of function ‘or1k_critical_end’ [-Wimplicit-function-declaration] 93 | or1k_critical_end(restore); | ^~~~~~~~~~~~~~~~~ This patch adds prototypes for functions or1k_critical_begin and or1k_critical_end to suppress the warning, inline with what we do for or1k_sync_cas. In libgloss/or1k/or1k_uart.c: libgloss/or1k/or1k_uart.c: In function ‘or1k_uart_set_read_cb’: libgloss/or1k/or1k_uart.c:163:25: warning: passing argument 2 of ‘or1k_interrupt_handler_add’ from incompatible pointer type [-Wincompatible-pointer-types] 163 | _or1k_uart_interrupt_handler, 0); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | void (*)(uint32_t) {aka void (*)(long unsigned int)} In file included from libgloss/or1k/or1k_uart.c:19: libgloss/or1k/include/or1k-support.h:97:45: note: expected ‘or1k_interrupt_handler_fptr’ {aka ‘void (*)(void *)’} but argument is of type ‘void (*)(uint32_t)’ {aka ‘void (*)(long unsigned int)’} 97 | or1k_interrupt_handler_fptr handler, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~ The public API is ‘void (*)(void *)' for our interrupt handlers. The function _or1k_uart_interrupt_hander is the internal default implementation of the uart IRQ handler and it doesn't use the data argument. This patch updates the _or1k_uart_interrupt_handler argument type from uint32_t to void* allowing the function prototype to match the required prototype. If we did have a 64-bit implementation it would be an ABI issue. But, there never has been one, or1k is only 32-bit. In libgloss/or1k/interrupts.c: libgloss/or1k/interrupts.c: In function ‘or1k_interrupt_handler_add’: libgloss/or1k/interrupts.c:41:52: warning: assignment to ‘void *’ from ‘long unsigned int’ makes pointer from integer without a cast [-Wint-conversion] 41 | _or1k_interrupt_handler_data_ptr_table[id] = (uint32_t) data_ptr; | ^ The table _or1k_interrupt_handler_data_ptr_table is an array of void* and data_ptr is void*. There is no need for the cast so remove it. In libgloss/or1k/sbrk.c: libgloss/or1k/sbrk.c:23:29: warning: initialization of ‘uint32_t’ {aka ‘long unsigned int’} from ‘uint32_t *’ {aka ‘long unsigned int *’} makes integer from pointer without a cast [-Wint-conversion] 23 | uint32_t _or1k_heap_start = &end; | This patch adds a cast, which is safe in or1k as the architecture in 32-bit only. But this code would not be 64-compatible. Signed-off-by: Stafford Horne --- libgloss/or1k/interrupts.c | 4 ++-- libgloss/or1k/or1k_uart.c | 2 +- libgloss/or1k/or1k_uart.h | 2 +- libgloss/or1k/sbrk.c | 2 +- newlib/libc/sys/or1k/mlock.c | 3 +++ 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/libgloss/or1k/interrupts.c b/libgloss/or1k/interrupts.c index 6badc497c..516d74be3 100644 --- a/libgloss/or1k/interrupts.c +++ b/libgloss/or1k/interrupts.c @@ -35,10 +35,10 @@ void or1k_interrupt_handler_add(uint32_t id, { #ifdef __OR1K_MULTICORE__ _or1k_interrupt_handler_table[or1k_coreid()][id] = handler; - _or1k_interrupt_handler_data_ptr_table[or1k_coreid()][id] = (uint32_t) data_ptr; + _or1k_interrupt_handler_data_ptr_table[or1k_coreid()][id] = data_ptr; #else _or1k_interrupt_handler_table[id] = handler; - _or1k_interrupt_handler_data_ptr_table[id] = (uint32_t) data_ptr; + _or1k_interrupt_handler_data_ptr_table[id] = data_ptr; #endif } diff --git a/libgloss/or1k/or1k_uart.c b/libgloss/or1k/or1k_uart.c index 0a991e6ba..1391d565c 100644 --- a/libgloss/or1k/or1k_uart.c +++ b/libgloss/or1k/or1k_uart.c @@ -90,7 +90,7 @@ void (*_or1k_uart_read_cb)(char c); * This is the interrupt handler that is registered for the callback * function. */ -void _or1k_uart_interrupt_handler(uint32_t data) +void _or1k_uart_interrupt_handler(void *data) { uint8_t iir = REG8(IIR); diff --git a/libgloss/or1k/or1k_uart.h b/libgloss/or1k/or1k_uart.h index 4cbb68350..201b7749f 100644 --- a/libgloss/or1k/or1k_uart.h +++ b/libgloss/or1k/or1k_uart.h @@ -30,7 +30,7 @@ extern void (*_or1k_uart_read_cb)(char c); /** * The UART interrupt handler */ -void _or1k_uart_interrupt_handler(uint32_t data); +void _or1k_uart_interrupt_handler(void *data); /** * Initialize UART diff --git a/libgloss/or1k/sbrk.c b/libgloss/or1k/sbrk.c index 0c3e66e87..ca196d228 100644 --- a/libgloss/or1k/sbrk.c +++ b/libgloss/or1k/sbrk.c @@ -20,7 +20,7 @@ #include "include/or1k-support.h" extern uint32_t end; /* Set by linker. */ -uint32_t _or1k_heap_start = &end; +uint32_t _or1k_heap_start = (uint32_t) &end; uint32_t _or1k_heap_end; void * diff --git a/newlib/libc/sys/or1k/mlock.c b/newlib/libc/sys/or1k/mlock.c index ccb840161..a0c038335 100644 --- a/newlib/libc/sys/or1k/mlock.c +++ b/newlib/libc/sys/or1k/mlock.c @@ -38,6 +38,9 @@ volatile uint32_t _or1k_malloc_lock_restore; extern uint32_t or1k_sync_cas(void *address, uint32_t compare, uint32_t swap); +extern uint32_t or1k_critical_begin(); +extern void or1k_critical_end(uint32_t restore); + /** * Recursive lock of the malloc */ From 14dda1f59871a12eb8e43141bf79d1dd89341ce2 Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Thu, 12 Dec 2024 17:22:55 +0100 Subject: [PATCH 04/10] Cygwin: doc: add SCHED_BATCH, SCHED_IDLE and SCHED_RESET_ON_FORK Signed-off-by: Christian Franke --- winsup/doc/posix.xml | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/winsup/doc/posix.xml b/winsup/doc/posix.xml index 436ab00a7..2782beb86 100644 --- a/winsup/doc/posix.xml +++ b/winsup/doc/posix.xml @@ -1771,25 +1771,32 @@ Over-allocation on sparse files is entirely ignored on Windows. sched_setpolicy only emulates API behavior because Windows does not offer alternative scheduling policies. -If SCHED_OTHER is selected, the Windows priority is -set according to the nice value. If SCHED_FIFO -or SCHED_RR is selected, the nice value is preserved -and the Windows priority is set according to the -sched_priority value. +If SCHED_OTHER or SCHED_BATCH is +selected, the Windows priority is set according to the nice value. +If SCHED_IDLE is selected, the Windows priority is +set to IDLE_PRIORITY_CLASS. +If SCHED_FIFO or SCHED_RR is +selected, the nice value is preserved and the Windows priority is set +according to the sched_priority value. +If the SCHED_RESET_ON_FORK flag is set, realtime +policies and negative nice values are dropped on +fork. nice, setpriority, sched_setparam and sched_setpolicy -map the nice value (SCHED_OTHER) or the -sched_priority (SCHED_FIFO, -SCHED_RR) to Windows priority classes as follows: +map the nice value (SCHED_OTHER, +SCHED_BATCH) or the sched_priority +(SCHED_FIFO, SCHED_RR) to Windows +priority classes as follows: - nice value sched_priority Windows priority class - 12...19 1....6 IDLE_PRIORITY_CLASS - 4...11 7...12 BELOW_NORMAL_PRIORITY_CLASS - -4....3 13...18 NORMAL_PRIORITY_CLASS - -12...-5 19...24 ABOVE_NORMAL_PRIORITY_CLASS - -13..-19 25...30 HIGH_PRIORITY_CLASS - -20 31...32 REALTIME_PRIORITY_CLASS + SCHED_OTHER SCHED_BATCH SCHED_FIFO/RR + nice value nice value sched_priority Windows priority class + 12...19 4...19 1....6 IDLE_PRIORITY_CLASS + 4...11 -4....3 7...12 BELOW_NORMAL_PRIORITY_CLASS + -4....3 -12...-5 13...18 NORMAL_PRIORITY_CLASS + -12...-5 -13..-19 19...24 ABOVE_NORMAL_PRIORITY_CLASS + -13..-19 -20 25...30 HIGH_PRIORITY_CLASS + -20 - 31...32 REALTIME_PRIORITY_CLASS The use of values which are mapped to the REALTIME_PRIORITY_CLASS require administrative From efa5401ea998ee01d79c63449f51cd36df938f42 Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Mon, 16 Dec 2024 17:32:55 +0100 Subject: [PATCH 05/10] Cygwin: /proc//stat: set field (18) according to scheduling policy If a realtime policy is selected, set the '(18) priority' field to the negated sched_priority minus one. If SCHED_IDLE is selected, set it to the lowest priority 39. Also set '(19) nice' to the originally requested nice value. Ensure consistence with the current Windows priority in all cases. Move the sched_priority from/to Windows priority mapping from sched_get/setparam() to new functions in miscfuncs.cc. Signed-off-by: Christian Franke --- winsup/cygwin/fhandler/process.cc | 26 +++++++++-- winsup/cygwin/local_includes/miscfuncs.h | 2 + winsup/cygwin/miscfuncs.cc | 56 ++++++++++++++++++++++-- winsup/cygwin/release/3.6.0 | 5 +++ winsup/cygwin/sched.cc | 40 +++-------------- 5 files changed, 88 insertions(+), 41 deletions(-) diff --git a/winsup/cygwin/fhandler/process.cc b/winsup/cygwin/fhandler/process.cc index 37bdff84e..e0aebb648 100644 --- a/winsup/cygwin/fhandler/process.cc +++ b/winsup/cygwin/fhandler/process.cc @@ -1098,7 +1098,6 @@ format_process_stat (void *data, char *&destbuf) unsigned long fault_count = 0UL, vmsize = 0UL, vmrss = 0UL, vmmaxrss = 0UL; uint64_t utime = 0ULL, stime = 0ULL, start_time = 0ULL; - int nice = 0; /* ctty maj is 31:16, min is 15:0; tty_nr s/b maj 15:8, min 31:20, 7:0; maj is 31:16 >> 16 & fff << 8; min is 15:0 >> 8 & ff << 20 | & ff */ int tty_nr = 0; @@ -1131,6 +1130,8 @@ format_process_stat (void *data, char *&destbuf) else state = get_process_state (p->dwProcessId); + int nice = 0, prio = 0; + NTSTATUS status; HANDLE hProcess; VM_COUNTERS vmc = { 0 }; @@ -1168,7 +1169,26 @@ format_process_stat (void *data, char *&destbuf) if (!NT_SUCCESS (status)) debug_printf ("NtQueryInformationProcess(ProcessQuotaLimits): " "status %y", status); - nice = winprio_to_nice (GetPriorityClass (hProcess)); + + nice = p->nice; + DWORD winprio = GetPriorityClass (hProcess); + if (p->sched_policy == SCHED_FIFO || p->sched_policy == SCHED_RR) + /* Linux proc_pid_stat(5): (18) priority - For processes running a + real-time scheduling policy ..., this is the negated scheduling + priority, minus one. */ + prio = - winprio_to_schedprio (winprio) - 1; /* -33(high)...-2(low) */ + else if (p->sched_policy == SCHED_IDLE) + /* Return the lowest priority unless no longer consistent. */ + prio = NZERO + (winprio == IDLE_PRIORITY_CLASS ? NZERO - 1 : + winprio_to_nice (winprio)); + else + { + /* Use originally requested nice value unless no longer consistent. */ + bool batch = (p->sched_policy == SCHED_BATCH); + if (winprio != nice_to_winprio (nice, batch)) + nice = winprio_to_nice (winprio, batch); + prio = NZERO + nice; /* 0(high)...39(low) */ + } CloseHandle (hProcess); } status = NtQuerySystemInformation (SystemTimeOfDayInformation, @@ -1201,7 +1221,7 @@ format_process_stat (void *data, char *&destbuf) p->ppid, p->pgid, p->sid, tty_nr, -1, 0, fault_count, fault_count, 0, 0, utime, stime, utime, stime, - NZERO + nice, nice, 0, 0, + prio, nice, 0, 0, start_time, vmsize, vmrss, vmmaxrss ); diff --git a/winsup/cygwin/local_includes/miscfuncs.h b/winsup/cygwin/local_includes/miscfuncs.h index 6001a1636..fd10e40f1 100644 --- a/winsup/cygwin/local_includes/miscfuncs.h +++ b/winsup/cygwin/local_includes/miscfuncs.h @@ -46,6 +46,8 @@ is_alt_numpad_event (PINPUT_RECORD pirec) int winprio_to_nice (DWORD prio, bool batch = false); DWORD nice_to_winprio (int &nice, bool batch = false); +int winprio_to_schedprio (DWORD prio); +DWORD schedprio_to_winprio (int schedprio); bool set_and_check_winprio (HANDLE proc, DWORD prio, bool set = true); bool create_pipe (PHANDLE, PHANDLE, LPSECURITY_ATTRIBUTES, DWORD); diff --git a/winsup/cygwin/miscfuncs.cc b/winsup/cygwin/miscfuncs.cc index 6faf04937..31080d043 100644 --- a/winsup/cygwin/miscfuncs.cc +++ b/winsup/cygwin/miscfuncs.cc @@ -104,7 +104,7 @@ yield () } /* - Mapping of nice value from/to Windows priority + Mapping of nice value or sched_priority from/to Windows priority ('batch' is used for SCHED_BATCH policy). nice_to_winprio() winprio_to_nice() @@ -115,6 +115,14 @@ yield () -12...-5 -13..-19 3 ABOVE_NORMAL_PRIORITY_CLASS -8 -16 -13..-19 -20 4 HIGH_PRIORITY_CLASS -16 -20 -20 - 5 REALTIME_PRIORITY_CLASS -20 -20 + + schedprio_to_winprio() winprio_to_schedprio() + 1....6 0 IDLE_PRIORITY_CLASS 3 + 7...12 1 BELOW_NORMAL_PRIORITY_CLASS 9 + 13...18 2 NORMAL_PRIORITY_CLASS 15 + 19...24 3 ABOVE_NORMAL_PRIORITY_CLASS 21 + 25...30 4 HIGH_PRIORITY_CLASS 27 + 31...32 5 REALTIME_PRIORITY_CLASS 32 */ /* *_PRIORITY_CLASS -> 0...5 */ @@ -167,9 +175,25 @@ nice_to_winprio_impl (int nice, bool batch = false) return level_to_winprio (level); } +/* *_PRIORITY_CLASS -> sched_priority */ +constexpr int +winprio_to_schedprio_impl (DWORD prio) +{ + int level = winprio_to_level (prio); + return (level < 5 ? 3 + level * 6 : 32); +} + +/* sched_priority -> *_PRIORITY_CLASS */ +constexpr DWORD +schedprio_to_winprio_impl (int schedprio) +{ + int level = (schedprio <= 1 ? 0 : (schedprio < 32 ? (schedprio - 1) / 6 : 5)); + return level_to_winprio (level); +} + /* Check consistency at compile time. */ constexpr bool -check_nice_winprio_mapping () +check_nice_schedprio_winprio_mapping () { for (int nice = -NZERO; nice < NZERO; nice++) for (int batch = 0; batch <= 1; batch++) { @@ -179,16 +203,28 @@ check_nice_winprio_mapping () if (prio != prio2) return false; } + for (int schedprio = 1; schedprio <= 32; schedprio++) + { + DWORD prio = schedprio_to_winprio_impl (schedprio); + int schedprio2 = winprio_to_schedprio_impl (prio); + DWORD prio2 = schedprio_to_winprio_impl (schedprio2); + if (prio != prio2) + return false; + } return true; } -static_assert (check_nice_winprio_mapping()); +static_assert (check_nice_schedprio_winprio_mapping()); static_assert (nice_to_winprio_impl(NZERO-1, false) == IDLE_PRIORITY_CLASS); static_assert (nice_to_winprio_impl(0, true) == BELOW_NORMAL_PRIORITY_CLASS); static_assert (winprio_to_nice_impl(BELOW_NORMAL_PRIORITY_CLASS, true) == 0); static_assert (nice_to_winprio_impl(0, false) == NORMAL_PRIORITY_CLASS); static_assert (winprio_to_nice_impl(NORMAL_PRIORITY_CLASS, false) == 0); static_assert (nice_to_winprio_impl(-NZERO, false) == REALTIME_PRIORITY_CLASS); +static_assert (schedprio_to_winprio_impl(1) == IDLE_PRIORITY_CLASS); +static_assert (schedprio_to_winprio_impl(15) == NORMAL_PRIORITY_CLASS); +static_assert (winprio_to_schedprio_impl(NORMAL_PRIORITY_CLASS) == 15); +static_assert (schedprio_to_winprio_impl(32) == REALTIME_PRIORITY_CLASS); /* Get a default value for the nice factor. */ int @@ -210,6 +246,20 @@ nice_to_winprio (int &nice, bool batch /* = false */) return nice_to_winprio_impl (nice, batch); } +/* Get a default sched_priority from a Win32 priority. */ +int +winprio_to_schedprio (DWORD prio) +{ + return winprio_to_schedprio_impl (prio); +} + +/* Get a Win32 priority matching the sched_priority. */ +DWORD +schedprio_to_winprio (int schedprio) +{ + return schedprio_to_winprio_impl (schedprio); +} + /* Set Win32 priority or return false on failure. Also return false and revert to the original priority if a different (lower) priority is set instead. Always revert to original priority if diff --git a/winsup/cygwin/release/3.6.0 b/winsup/cygwin/release/3.6.0 index 4e0726e8f..47c19a86b 100644 --- a/winsup/cygwin/release/3.6.0 +++ b/winsup/cygwin/release/3.6.0 @@ -69,3 +69,8 @@ What changed: each child process created with fork(2). Note: Windows does not offer alternative scheduling policies so this could only emulate API behavior. + +- If SCHED_FIFO or SCHED_RR is selected, the /proc//stat field + '(18) priority' is now set to the negated sched_policy minus one. + If SCHED_IDLE is selected, this field is set to 39. The '(19) nice' + field is now set to the originally requested nice value. diff --git a/winsup/cygwin/sched.cc b/winsup/cygwin/sched.cc index d75a3404f..43b17357b 100644 --- a/winsup/cygwin/sched.cc +++ b/winsup/cygwin/sched.cc @@ -120,29 +120,7 @@ sched_getparam (pid_t pid, struct sched_param *param) return -1; } /* calculate the unix priority. */ - switch (pclass) - { - case IDLE_PRIORITY_CLASS: - param->sched_priority = 3; - break; - case BELOW_NORMAL_PRIORITY_CLASS: - param->sched_priority = 9; - break; - case NORMAL_PRIORITY_CLASS: - default: - param->sched_priority = 15; - break; - case ABOVE_NORMAL_PRIORITY_CLASS: - param->sched_priority = 21; - break; - case HIGH_PRIORITY_CLASS: - param->sched_priority = 27; - break; - case REALTIME_PRIORITY_CLASS: - param->sched_priority = 32; - break; - } - + param->sched_priority = winprio_to_schedprio (pclass); return 0; } @@ -244,18 +222,10 @@ sched_setparam_pinfo (pinfo & p, const struct sched_param *param) else if (p->sched_policy == SCHED_IDLE && pri == 0) /* Idle policy, ignore the nice value. */ pclass = IDLE_PRIORITY_CLASS; - else if (1 <= pri && pri <= 6) - pclass = IDLE_PRIORITY_CLASS; - else if (pri <= 12) - pclass = BELOW_NORMAL_PRIORITY_CLASS; - else if (pri <= 18) - pclass = NORMAL_PRIORITY_CLASS; - else if (pri <= 24) - pclass = ABOVE_NORMAL_PRIORITY_CLASS; - else if (pri <= 30) - pclass = HIGH_PRIORITY_CLASS; - else if (pri <= 32) - pclass = REALTIME_PRIORITY_CLASS; + else if ((p->sched_policy == SCHED_FIFO || p->sched_policy == SCHED_RR) + && valid_sched_parameters (param)) + /* Realtime policy, apply requested priority. */ + pclass = schedprio_to_winprio (param->sched_priority); else { set_errno (EINVAL); From 677e3150907a83f17e50d546f79b7ca863ebd77d Mon Sep 17 00:00:00 2001 From: Ken Brown Date: Wed, 18 Dec 2024 11:39:31 -0500 Subject: [PATCH 06/10] Cygwin: mmap: fix protection when unused pages are recycled Previously, when unused pages from an mmap_record were recycled, they were given the protection of the mmap_record rather than the protection requested in the mmap call. Fix this by adding a "new_prot" parameter to mmap_list::try_map() and mmap_record::map_pages() to keep track of the requested protection. Then use new_prot in the calls to VirtualProtect(). Addresses: https://cygwin.com/pipermail/cygwin/2024-December/256911.html Fixes: f90e23f2714cb ("*autoload.cc (NtCreateSection): Define.") Signed-off-by: Ken Brown --- winsup/cygwin/mm/mmap.cc | 31 ++++++++++++++++++------------- winsup/cygwin/release/3.5.5 | 3 +++ 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/winsup/cygwin/mm/mmap.cc b/winsup/cygwin/mm/mmap.cc index 332c015a7..4fec64b87 100644 --- a/winsup/cygwin/mm/mmap.cc +++ b/winsup/cygwin/mm/mmap.cc @@ -339,8 +339,8 @@ class mmap_record SIZE_T find_unused_pages (SIZE_T pages) const; bool match (caddr_t addr, SIZE_T len, caddr_t &m_addr, SIZE_T &m_len); - off_t map_pages (SIZE_T len); - bool map_pages (caddr_t addr, SIZE_T len); + off_t map_pages (SIZE_T len, int new_prot); + bool map_pages (caddr_t addr, SIZE_T len, int new_prot); bool unmap_pages (caddr_t addr, SIZE_T len); int access (caddr_t address); @@ -373,7 +373,8 @@ class mmap_list void set (int nfd, struct stat *st); mmap_record *add_record (mmap_record &r); bool del_record (mmap_record *rec); - caddr_t try_map (void *addr, size_t len, int flags, off_t off); + caddr_t try_map (void *addr, size_t len, int new_prot, int flags, + off_t off); }; class mmap_areas @@ -455,14 +456,15 @@ mmap_record::init_page_map (mmap_record &r) } off_t -mmap_record::map_pages (SIZE_T len) +mmap_record::map_pages (SIZE_T len, int new_prot) { /* Used ONLY if this mapping matches into the chunk of another already performed mapping in a special case of MAP_ANON|MAP_PRIVATE. Otherwise it's job is now done by init_page_map(). */ DWORD old_prot; - debug_printf ("map_pages (fd=%d, len=%lu)", get_fd (), len); + debug_printf ("map_pages (fd=%d, len=%lu, new_prot=%y)", get_fd (), len, + new_prot); len = PAGE_CNT (len); off_t off = find_unused_pages (len); @@ -470,7 +472,8 @@ mmap_record::map_pages (SIZE_T len) return (off_t) 0; if (!noreserve () && !VirtualProtect (get_address () + off * wincap.page_size (), - len * wincap.page_size (), gen_protect (), + len * wincap.page_size (), + ::gen_protect (new_prot, get_flags ()), &old_prot)) { __seterrno (); @@ -483,9 +486,10 @@ mmap_record::map_pages (SIZE_T len) } bool -mmap_record::map_pages (caddr_t addr, SIZE_T len) +mmap_record::map_pages (caddr_t addr, SIZE_T len, int new_prot) { - debug_printf ("map_pages (addr=%p, len=%lu)", addr, len); + debug_printf ("map_pages (addr=%p, len=%lu, new_prot=%y)", addr, len, + new_prot); DWORD old_prot; off_t off = addr - get_address (); off /= wincap.page_size (); @@ -499,7 +503,8 @@ mmap_record::map_pages (caddr_t addr, SIZE_T len) } if (!noreserve () && !VirtualProtect (get_address () + off * wincap.page_size (), - len * wincap.page_size (), gen_protect (), + len * wincap.page_size (), + ::gen_protect (new_prot, get_flags ()), &old_prot)) { __seterrno (); @@ -614,7 +619,7 @@ mmap_list::del_record (mmap_record *rec) } caddr_t -mmap_list::try_map (void *addr, size_t len, int flags, off_t off) +mmap_list::try_map (void *addr, size_t len, int new_prot, int flags, off_t off) { mmap_record *rec; @@ -628,7 +633,7 @@ mmap_list::try_map (void *addr, size_t len, int flags, off_t off) break; if (rec && rec->compatible_flags (flags)) { - if ((off = rec->map_pages (len)) == (off_t) -1) + if ((off = rec->map_pages (len, new_prot)) == (off_t) -1) return (caddr_t) MAP_FAILED; return (caddr_t) rec->get_address () + off; } @@ -655,7 +660,7 @@ mmap_list::try_map (void *addr, size_t len, int flags, off_t off) set_errno (EINVAL); return (caddr_t) MAP_FAILED; } - if (!rec->map_pages ((caddr_t) addr, len)) + if (!rec->map_pages ((caddr_t) addr, len, new_prot)) return (caddr_t) MAP_FAILED; return (caddr_t) addr; } @@ -1051,7 +1056,7 @@ go_ahead: /* Test if an existing anonymous mapping can be recycled. */ if (map_list && anonymous (flags)) { - caddr_t tried = map_list->try_map (addr, len, flags, off); + caddr_t tried = map_list->try_map (addr, len, prot, flags, off); /* try_map returns NULL if no map matched, otherwise it returns a valid address, or MAP_FAILED in case of a fatal error. */ if (tried) diff --git a/winsup/cygwin/release/3.5.5 b/winsup/cygwin/release/3.5.5 index e99739241..eb97c3d4a 100644 --- a/winsup/cygwin/release/3.5.5 +++ b/winsup/cygwin/release/3.5.5 @@ -61,3 +61,6 @@ Fixes: - Fix several problems triggered when a lot of SIGSTOP/SIGCONT signals are received rapidly. Addresses: https://cygwin.com/pipermail/cygwin/2024-November/256744.html + +- Fix the protection when mmap(2) recycles unused pages. + Addresses: https://cygwin.com/pipermail/cygwin/2024-December/256911.html From 67bef16f7edf8642366ff55399bf9cf007c66d52 Mon Sep 17 00:00:00 2001 From: Ken Brown Date: Wed, 18 Dec 2024 11:43:09 -0500 Subject: [PATCH 07/10] Cygwin: mmap_list::try_map: fix a condition in a test of an mmap request In testing whether the requested area is contained in an existing mapped region, an incorrect condition was used due to a misinterpretation of the u_addr and u_len variables. Addresses: https://cygwin.com/pipermail/cygwin/2024-December/256913.html Fixes: c68de3a262fe5 ("* mmap.cc (class mmap_record): Declare new map_pages method with address parameter.") Signed-off-by: Ken Brown --- winsup/cygwin/mm/mmap.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/winsup/cygwin/mm/mmap.cc b/winsup/cygwin/mm/mmap.cc index 4fec64b87..13418d782 100644 --- a/winsup/cygwin/mm/mmap.cc +++ b/winsup/cygwin/mm/mmap.cc @@ -651,7 +651,7 @@ mmap_list::try_map (void *addr, size_t len, int new_prot, int flags, off_t off) break; if (rec) { - if (u_addr > (caddr_t) addr || u_addr + len < (caddr_t) addr + len + if (u_addr > (caddr_t) addr || u_addr + u_len < (caddr_t) addr + len || !rec->compatible_flags (flags)) { /* Partial match only, or access mode doesn't match. */ From 363357c023ce01e936bdaedf0f479292a8fa4e0f Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Thu, 19 Dec 2024 19:52:56 +0100 Subject: [PATCH 08/10] Cygwin: pinfo: raise MAX_PID to 4194304 Reportedly, the maximum pid of 65536 is much too small in bigger environments. Raise the maximum PID to 4194304, whihc is the maximum pid on Linux (PID_MAX_LIMIT defined in include/linux/threads.h). Signed-off-by: Corinna Vinschen --- winsup/cygwin/local_includes/pinfo.h | 2 +- winsup/cygwin/pinfo.cc | 2 +- winsup/cygwin/release/3.6.0 | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/winsup/cygwin/local_includes/pinfo.h b/winsup/cygwin/local_includes/pinfo.h index be5d53021..4de0f80dd 100644 --- a/winsup/cygwin/local_includes/pinfo.h +++ b/winsup/cygwin/local_includes/pinfo.h @@ -223,7 +223,7 @@ private: DWORD status_exit (DWORD); }; -#define MAX_PID 65536 +#define MAX_PID 4194304 #define ISSTATE(p, f) (!!((p)->process_state & f)) #define NOTSTATE(p, f) (!((p)->process_state & f)) diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc index fecf76eb6..1f26a3ccd 100644 --- a/winsup/cygwin/pinfo.cc +++ b/winsup/cygwin/pinfo.cc @@ -239,7 +239,7 @@ pinfo::exit (DWORD n) } # undef self -/* Return next free Cygwin PID between 2 and 65535, round-robin. Each new +/* Return next free Cygwin PID between 2 and MAX_PID, round-robin. Each new PID is checked that it doesn't collide with an existing PID. For that, just check if the "cygpid.PID" section exists. */ pid_t diff --git a/winsup/cygwin/release/3.6.0 b/winsup/cygwin/release/3.6.0 index 47c19a86b..4b7604907 100644 --- a/winsup/cygwin/release/3.6.0 +++ b/winsup/cygwin/release/3.6.0 @@ -74,3 +74,7 @@ What changed: '(18) priority' is now set to the negated sched_policy minus one. If SCHED_IDLE is selected, this field is set to 39. The '(19) nice' field is now set to the originally requested nice value. + +- Raise maximum pid from 65536 to 4194304 to account for scenarios + with lots of CPUs and lots of tasks. + Addresses: https://cygwin.com/pipermail/cygwin/2024-December/256927.html From 5e5e51f1dc56a99eb4648c28e00d73b6ea44a8b0 Mon Sep 17 00:00:00 2001 From: Jeff Johnston Date: Tue, 31 Dec 2024 20:35:33 -0500 Subject: [PATCH 09/10] Changes for 4.5.0 snapshot - bump up release to 4.5.0 --- newlib/NEWS | 16 ++++++++++++++++ newlib/README | 18 +++++++++--------- newlib/acinclude.m4 | 2 +- newlib/configure | 24 ++++++++++++------------ newlib/libc/libc.texi | 4 ++-- newlib/libm/libm.texi | 4 ++-- 6 files changed, 42 insertions(+), 26 deletions(-) diff --git a/newlib/NEWS b/newlib/NEWS index 348cb4d7d..ce4391367 100644 --- a/newlib/NEWS +++ b/newlib/NEWS @@ -1,3 +1,19 @@ +*** Major changes in newlib version 4.5.0: + +- major clean-up of libgloss build including merging a number of platforms + into top-level Makefile (moxie, v850, i960, msp430, frv, i386, ...) and + removal of dead platforms such as xc16x +- strverscmp fixed for comparison of digit sequence with non-digits +- proper locking added from amdgcn +- numerous improvements to arc support including support of 16-entry + register file +- long double complex functions are now skipped if long double != double +- support for POSIX.1-2024 added to features.h +- arc64: port added for Synopsys Designware ARCv3 ISA +- sys/xtensa removed and replaced by machine/xtensa and libgloss +- fixes to powf +- fixes for building with gcc-15 + *** Major changes in newlib version 4.4.0: - long double support for i386, aarch64, and x86_64 added from FreeBSD diff --git a/newlib/README b/newlib/README index 1b2c16cd4..69496f695 100644 --- a/newlib/README +++ b/newlib/README @@ -1,4 +1,4 @@ - README for newlib-4.2.0 release + README for newlib-4.5.0 release (mostly cribbed from the README in the gdb-4.13 release) This is `newlib', a simple ANSI C library, math library, and collection @@ -20,8 +20,8 @@ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Unpacking and Installation -- quick overview ========================== -When you unpack the newlib-4.2.0.tar.gz file, you'll find a directory -called `newlib-4.2.0', which contains many files. Interesting ones: +When you unpack the newlib-4.5.0.tar.gz file, you'll find a directory +called `newlib-4.5.0', which contains many files. Interesting ones: COPYING* - License files for the sources README - A common overview of all GNU development projects configure - The build script for configuring the source tree @@ -94,13 +94,13 @@ directory. If the path to `configure' would be the same as the argument to `--srcdir', you can leave out the `--srcdir' option; it will be assumed.) - For example, with version 4.2.0, you can build NEWLIB in a separate + For example, with version 4.5.0, you can build NEWLIB in a separate directory for a Sun 4 cross m68k-aout environment like this: - cd newlib-4.2.0 + cd newlib-4.5.0 mkdir ../newlib-m68k-aout cd ../newlib-m68k-aout - ../newlib-4.2.0/configure --host=sun4 --target=m68k-aout + ../newlib-4.5.0/configure --host=sun4 --target=m68k-aout make When `configure' builds a configuration using a remote source @@ -116,8 +116,8 @@ called `configure' (or one of its subdirectories). The `Makefile' that `configure' generates in each source directory also runs recursively. If you type `make' in a source directory such -as `newlib-4.2.0' (or in a separate configured directory configured with -`--srcdir=PATH/newlib-4.2.0'), you will build all the required libraries. +as `newlib-4.5.0' (or in a separate configured directory configured with +`--srcdir=PATH/newlib-4.5.0'), you will build all the required libraries. When you have multiple hosts or targets configured in separate directories, you can run `make' on them in parallel (for example, if @@ -530,7 +530,7 @@ Reporting Bugs The correct address for reporting bugs found in NEWLIB is "newlib@sourceware.org". Please email all bug reports to that -address. Please include the NEWLIB version number (e.g., newlib-4.2.0), +address. Please include the NEWLIB version number (e.g., newlib-4.5.0), and how you configured it (e.g., "sun4 host and m68k-aout target"). Since NEWLIB supports many different configurations, it is important that you be precise about this. diff --git a/newlib/acinclude.m4 b/newlib/acinclude.m4 index 2f8fb8d0f..19301289f 100644 --- a/newlib/acinclude.m4 +++ b/newlib/acinclude.m4 @@ -2,7 +2,7 @@ dnl This provides configure definitions used by all the newlib dnl configure.in files. AC_DEFUN([DEF_NEWLIB_MAJOR_VERSION],m4_define([NEWLIB_MAJOR_VERSION],[4])) -AC_DEFUN([DEF_NEWLIB_MINOR_VERSION],m4_define([NEWLIB_MINOR_VERSION],[4])) +AC_DEFUN([DEF_NEWLIB_MINOR_VERSION],m4_define([NEWLIB_MINOR_VERSION],[5])) AC_DEFUN([DEF_NEWLIB_PATCHLEVEL_VERSION],m4_define([NEWLIB_PATCHLEVEL_VERSION],[0])) AC_DEFUN([DEF_NEWLIB_VERSION],m4_define([NEWLIB_VERSION],[NEWLIB_MAJOR_VERSION.NEWLIB_MINOR_VERSION.NEWLIB_PATCHLEVEL_VERSION])) diff --git a/newlib/configure b/newlib/configure index e7158c063..bf8d08100 100755 --- a/newlib/configure +++ b/newlib/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for newlib 4.4.0. +# Generated by GNU Autoconf 2.69 for newlib 4.5.0. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -576,8 +576,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='newlib' PACKAGE_TARNAME='newlib' -PACKAGE_VERSION='4.4.0' -PACKAGE_STRING='newlib 4.4.0' +PACKAGE_VERSION='4.5.0' +PACKAGE_STRING='newlib 4.5.0' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1563,7 +1563,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures newlib 4.4.0 to adapt to many kinds of systems. +\`configure' configures newlib 4.5.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1633,7 +1633,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of newlib 4.4.0:";; + short | recursive ) echo "Configuration of newlib 4.5.0:";; esac cat <<\_ACEOF @@ -1765,7 +1765,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -newlib configure 4.4.0 +newlib configure 4.5.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1857,7 +1857,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by newlib $as_me 4.4.0, which was +It was created by newlib $as_me 4.5.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -4870,7 +4870,7 @@ fi # Define the identity of the package. PACKAGE='newlib' - VERSION='4.4.0' + VERSION='4.5.0' # Some tools Automake needs. @@ -6501,13 +6501,13 @@ fi -$as_echo "#define _NEWLIB_VERSION \"4.4.0\"" >>confdefs.h +$as_echo "#define _NEWLIB_VERSION \"4.5.0\"" >>confdefs.h $as_echo "#define __NEWLIB__ 4" >>confdefs.h -$as_echo "#define __NEWLIB_MINOR__ 4" >>confdefs.h +$as_echo "#define __NEWLIB_MINOR__ 5" >>confdefs.h $as_echo "#define __NEWLIB_PATCHLEVEL__ 0" >>confdefs.h @@ -8460,7 +8460,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by newlib $as_me 4.4.0, which was +This file was extended by newlib $as_me 4.5.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -8526,7 +8526,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -newlib config.status 4.4.0 +newlib config.status 4.5.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/newlib/libc/libc.texi b/newlib/libc/libc.texi index 1d798d11e..965006206 100644 --- a/newlib/libc/libc.texi +++ b/newlib/libc/libc.texi @@ -69,8 +69,8 @@ into another language, under the above conditions for modified versions. @title The Red Hat newlib C Library @subtitle Full Configuration @sp 1 -@subtitle @code{libc} 4.4.0 -@subtitle December 2023 +@subtitle @code{libc} 4.5.0 +@subtitle December 2024 @author Steve Chamberlain @author Roland Pesch @author Red Hat Support diff --git a/newlib/libm/libm.texi b/newlib/libm/libm.texi index d322422c2..067676e30 100644 --- a/newlib/libm/libm.texi +++ b/newlib/libm/libm.texi @@ -46,8 +46,8 @@ into another language, under the above conditions for modified versions. @titlepage @title The Red Hat newlib C Math Library @sp 1 -@subtitle @code{libm} 4.4.0 -@subtitle December 2023 +@subtitle @code{libm} 4.5.0 +@subtitle December 2024 @author Steve Chamberlain @author Roland Pesch @author Red Hat Support From 0e1fbc94a2bc25b8be75b3c8762b2f264381728b Mon Sep 17 00:00:00 2001 From: Aiden Isik Date: Wed, 26 Feb 2025 21:58:24 +0000 Subject: [PATCH 10/10] Set up to compile for FreeChainXenon (random system at the moment, just need to compile GCC stage 2) --- config.sub | 2 +- newlib/configure.host | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config.sub b/config.sub index 38f3d037a..d099cebfb 100755 --- a/config.sub +++ b/config.sub @@ -1749,7 +1749,7 @@ case $os in | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \ - | fiwix* ) + | fiwix* | xenon* ) ;; # This one is extra strict with allowed versions sco3.2v2 | sco3.2v[4-9]* | sco5v6*) diff --git a/newlib/configure.host b/newlib/configure.host index ff2e51275..73f31f716 100644 --- a/newlib/configure.host +++ b/newlib/configure.host @@ -455,6 +455,9 @@ case "${host}" in newlib_cflags="${newlib_cflags} -DHAVE_FCNTL -DHAVE_BLKSIZE -DHAVE_OPENDIR -DHAVE_RENAME" newlib_cflags="${newlib_cflags} -DGETREENT_PROVIDED -DSIGNAL_PROVIDED" ;; + *-fcx-*) + sys_dir=amdgcn # Just use a random one for now, we don't use this yet. + ;; a29k-*-*) sys_dir=a29khif signal_dir=