From patchwork Mon Apr 8 11:07:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 88164 X-Patchwork-Delegate: szabolcs.nagy@arm.com Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 480DD384B06A for ; Mon, 8 Apr 2024 11:08:41 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 0E1593858432 for ; Mon, 8 Apr 2024 11:08:02 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 0E1593858432 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 0E1593858432 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1712574486; cv=none; b=DfCMBqAV4cIZ9ykyEoPAL2OIUqYRWC3zr5v2sw/4sHoqG8mMOaBDMmAck2/R6pJ52RqETlxg96DNg/va72y4TN3wHCY6ltIBLvHP+SNJPYTLVyhYByDxKo8DwSZOzHxvl9xSpHeSFSkcrj64YN0j/tx0UFotaFKQMiXRTDIHXUg= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1712574486; c=relaxed/simple; bh=8TtTWypfwg0pj9H1IZBvU6dCntttmFnsc/haG5SNE7c=; h=DKIM-Signature:From:To:Subject:Message-ID:Date:MIME-Version; b=cegJ3JEk5q+Mc7e17etGoyo5XpdWUMDJvUDOR2nvCaeG6KIarTslO4I/vvBoQNMgms8dTOtVVgWAJ9lteGMWD+Vg36nzGu834RemseYVQia7TPvm8SiQb0DGqK1eYa4norF/PXWaaVNckKXhI3gwSiM+KE7wY957xUMyUB54F8o= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1712574481; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=WN0U2JwGEXaG6jgdx/3LPrruMljuhFusEHyDz1o7s/8=; b=YNTzumLNcae/4pYuzEcD4rEKbvWbhTnQOo5XTAXY0LdWzYNa5LMoXsA8nd4Te7QLe9ycIp nLeMBjUp2D/11G0gV4HPSAk7Tq1syE8+lqmIFmO8mZ4Teh/ZaLaA3AdJxPyElTu+swMJel dAO0+hVY4ifAcilPQfwBUTjMuankJRc= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-523-9tGNDzmyMjO-plEmbGBREQ-1; Mon, 08 Apr 2024 07:08:00 -0400 X-MC-Unique: 9tGNDzmyMjO-plEmbGBREQ-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.rdu2.redhat.com [10.11.54.7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id E4698889F43 for ; Mon, 8 Apr 2024 11:07:59 +0000 (UTC) Received: from oldenburg.str.redhat.com (unknown [10.39.192.59]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 4CEF01C060A6 for ; Mon, 8 Apr 2024 11:07:59 +0000 (UTC) From: Florian Weimer To: libc-alpha@sourceware.org Subject: [PATCH v4 1/3] elf: Add CPU iteration support for future use in ld.so diagnostics In-Reply-To: Message-ID: References: X-From-Line: afcac701ac12c45cf830b4df0f13fc1d8835606a Mon Sep 17 00:00:00 2001 Date: Mon, 08 Apr 2024 13:07:53 +0200 User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.7 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.3 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org --- v4: Include in the generic version, to fix the Hurd build. elf/dl-iterate_cpu.h | 136 ++++++++++++++++++++++++++ sysdeps/generic/dl-affinity.h | 54 ++++++++++ sysdeps/unix/sysv/linux/dl-affinity.h | 46 +++++++++ 3 files changed, 236 insertions(+) create mode 100644 elf/dl-iterate_cpu.h create mode 100644 sysdeps/generic/dl-affinity.h create mode 100644 sysdeps/unix/sysv/linux/dl-affinity.h Reviewed-by: Szabolcs Nagy diff --git a/elf/dl-iterate_cpu.h b/elf/dl-iterate_cpu.h new file mode 100644 index 0000000000..60db167b13 --- /dev/null +++ b/elf/dl-iterate_cpu.h @@ -0,0 +1,136 @@ +/* Iterate over all CPUs, for CPU-specific diagnostics. + Copyright (C) 2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef DL_ITERATE_CPU_H +#define DL_ITERATE_CPU_H + +#include +#include + +struct dl_iterate_cpu +{ + /* Sequential iteration count, starting at 0. */ + unsigned int processor_index; + + /* Requested CPU. Can be -1 if affinity could not be set. */ + int requested_cpu; + + /* Observed current CPU. -1 if unavailable. */ + int actual_cpu; + + /* Observed node ID for the CPU. -1 if unavailable. */ + int actual_node; + + /* Internal fields to implement the iteration. */ + + /* Affinity as obtained by _dl_iterate_cpu_init, using + _dl_getaffinity. Space for 8,192 CPUs. */ + unsigned long int mask_reference[8192 / sizeof (unsigned long int) / 8]; + + /* This array is used by _dl_setaffinity calls. */ + unsigned long int mask_request[8192 / sizeof (unsigned long int) / 8]; + + /* Return value from the initial _dl_getaffinity call. */ + int length_reference; +}; + +static void +_dl_iterate_cpu_init (struct dl_iterate_cpu *dic) +{ + dic->length_reference + = _dl_getaffinity (dic->mask_reference, sizeof (dic->mask_reference)); + /* Prepare for the first _dl_iterate_cpu_next call. */ + dic->processor_index = -1; + dic->requested_cpu = -1; +} + +static bool +_dl_iterate_cpu_next (struct dl_iterate_cpu *dic) +{ + ++dic->processor_index; + + if (dic->length_reference > 0) + { + /* Search for the next CPU to switch to. */ + while (true) + { + ++dic->requested_cpu; + + /* Array index and bit number within the array. */ + unsigned int long_index + = dic->requested_cpu / sizeof (unsigned long int) / 8; + unsigned int bit_index + = dic->requested_cpu % (sizeof (unsigned long int) * 8); + + if (long_index * sizeof (unsigned long int) >= dic->length_reference) + /* All possible CPUs have been covered. */ + return false; + + unsigned long int bit = 1UL << bit_index; + if (dic->mask_reference[long_index] & bit) + { + /* The CPU is available. Try to select it. */ + dic->mask_request[long_index] = bit; + if (_dl_setaffinity (dic->mask_request, + (long_index + 1) + * sizeof (unsigned long int)) < 0) + { + /* Record that we could not perform a CPU request. */ + dic->length_reference = -1; + + if (dic->processor_index > 0) + /* We already reported something. There is no need to + continue because the new data is probably not useful. */ + return false; + } + + /* Clear the bit in case the next iteration switches to the + next long value. */ + dic->mask_request[long_index] = 0; + + /* We found a CPU to run on. */ + break; + } + } + } + else + { + /* No way to set CPU affinity. Iterate just once. */ + if (dic->processor_index > 0) + return false; + } + + /* Fill in the actual CPU information. CPU pinning may not actually + be effective, depending on the container host. */ + unsigned int cpu, node; + if (_dl_getcpu (&cpu, &node) < 0) + { + /* No CPU information available. */ + dic->actual_cpu = -1; + dic->actual_node = -1; + } + else + { + dic->actual_cpu = cpu; + dic->actual_node = node; + } + + return true; +} + +#endif /* DL_ITERATE_CPU_H */ diff --git a/sysdeps/generic/dl-affinity.h b/sysdeps/generic/dl-affinity.h new file mode 100644 index 0000000000..d117f737e9 --- /dev/null +++ b/sysdeps/generic/dl-affinity.h @@ -0,0 +1,54 @@ +/* CPU affinity handling for the dynamic linker. Stub version. + Copyright (C) 2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef DL_AFFINITY_H +#define DL_AFFINITY_H + +#include +#include + +/* On success, write the current CPU ID to *CPU, and the current node + ID to *NODE, and return 0. Return a negative error code on + failure. */ +static inline int +_dl_getcpu (unsigned int *cpu, unsigned int *node) +{ + return -ENOSYS; +} + +/* On success, write CPU ID affinity bits for the current thread to + *BITS, which must be SIZE bytes long, and return the number of + bytes updated, a multiple of sizeof (unsigned long int). On + failure, return a negative error code. */ +static int +_dl_getaffinity (unsigned long int *bits, size_t size) +{ + return -ENOSYS; +} + +/* Set the CPU affinity mask for the current thread to *BITS, using + the SIZE bytes from that array, which should be a multiple of + sizeof (unsigned long int). Return 0 on success, and a negative + error code on failure. */ +static int +_dl_setaffinity (const unsigned long int *bits, size_t size) +{ + return -ENOSYS; +} + +#endif /* DL_AFFINITY_H */ diff --git a/sysdeps/unix/sysv/linux/dl-affinity.h b/sysdeps/unix/sysv/linux/dl-affinity.h new file mode 100644 index 0000000000..bbfede7750 --- /dev/null +++ b/sysdeps/unix/sysv/linux/dl-affinity.h @@ -0,0 +1,46 @@ +/* CPU affinity handling for the dynamic linker. Linux version. + Copyright (C) 2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +/* See sysdeps/generic/dl-affinity.h for documentation of these interfaces. */ + +#ifndef DL_AFFINITY_H +#define DL_AFFINITY_H + +#include +#include +#include + +static inline int +_dl_getcpu (unsigned int *cpu, unsigned int *node) +{ + return INTERNAL_SYSCALL_CALL (getcpu, cpu, node); +} + +static int +_dl_getaffinity (unsigned long int *bits, size_t size) +{ + return INTERNAL_SYSCALL_CALL (sched_getaffinity, /* TID */ 0, size, bits); +} + +static int +_dl_setaffinity (const unsigned long int *bits, size_t size) +{ + return INTERNAL_SYSCALL_CALL (sched_setaffinity, /* TID */ 0, size, bits); +} + +#endif /* DL_AFFINITY_H */