From patchwork Fri Apr 25 20:09:55 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: DJ Delorie X-Patchwork-Id: 111047 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 D2E393858D38 for ; Fri, 25 Apr 2025 20:14:21 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org D2E393858D38 Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=OTWHq9eq 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 ESMTP id E075D385843B for ; Fri, 25 Apr 2025 20:09:59 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E075D385843B Authentication-Results: sourceware.org; dmarc=pass (p=quarantine 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 E075D385843B 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=1745611800; cv=none; b=Vf10pWSTQbxLcrlUS9Rkr8Jh3ecUGnMH4nIWeH58A5PBgBZF+fNTY+FfJhelovvudtdIvT7rVD++J+JCCTOQzBtHKquYwQfrmnTRTcQYy6ImaxC4tANMYE1fIaa/21Enz8BIcRzmDHyrp98cMt7Zzp2+QozGt2v6wBQILtCI+wY= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1745611800; c=relaxed/simple; bh=6DmfR1u1jJ0Aos21SwZYA4T5sO3/rc7tkgHodw5gbbk=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=fPfhBWinD3VOzbtwwfoNvlRk+Emf14/WeUvjp1Ins5XACjgtG74Y5e2mBsRAJB2aVvKCU8nZIsiYDK4mt4V5/dYfqxdcqRVyB69aDkOEgGwzvIgPLKTM+nuuOpOa1AmqE69du6GTlwW5yaIFJh4pqMvqZ3nSWlExnNcVLFD8kGw= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E075D385843B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1745611799; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to; bh=DwQhjka4asVAFqg16zUAEJwZ9RHsTzLjsGkAxP9zm1A=; b=OTWHq9eqgULetrPMJ011fqg+61aa9Pmid2SZ5CELjTnwjCF3DgoGeu+I4GDKJyVKwcZhyJ s5rSe8lEGIK0YVfOtkz6Mo9ivWd8sIX+8JDlVYicaOQu+fZOiUHX6Q9wh2lnTvDcwQuYEo /XprxHqSEJfiu7jbWYWuUwwEJK+oHMM= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-683-lDjSt8HFMBiefFViXSeEDw-1; Fri, 25 Apr 2025 16:09:58 -0400 X-MC-Unique: lDjSt8HFMBiefFViXSeEDw-1 X-Mimecast-MFC-AGG-ID: lDjSt8HFMBiefFViXSeEDw_1745611797 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (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 mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 6176D1800370 for ; Fri, 25 Apr 2025 20:09:57 +0000 (UTC) Received: from greed.delorie.com (unknown [10.22.88.241]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 0A7261800D97; Fri, 25 Apr 2025 20:09:56 +0000 (UTC) Received: from greed.delorie.com.redhat.com (localhost [127.0.0.1]) by greed.delorie.com (8.16.1/8.16.1) with ESMTP id 53PK9tXn3111587; Fri, 25 Apr 2025 16:09:55 -0400 From: DJ Delorie To: Florian Weimer Cc: libc-alpha@sourceware.org Subject: [patch v2] manual: add remaining CPU_* macros In-Reply-To: <874iycke4p.fsf@oldenburg.str.redhat.com> (message from Florian Weimer on Fri, 25 Apr 2025 07:24:06 +0200) Date: Fri, 25 Apr 2025 16:09:55 -0400 Message-ID: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: IYt7S28TCI34fnPazrnJN6mOINEMHsyliobXT4ovoVo_1745611797 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-10.8 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, PROLO_LEO2, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H5, RCVD_IN_MSPIKE_WL, RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED, 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 Adds remaining CPU_* macros, including the CPU_*_S macros for dynamic-sized cpu sets. Reviewed-by: Collin Funk diff --git a/manual/resource.texi b/manual/resource.texi index acdb1f3986..c824046d2d 100644 --- a/manual/resource.texi +++ b/manual/resource.texi @@ -1362,26 +1362,73 @@ extent the Linux kernel interface. @standards{GNU, sched.h} This data set is a bitset where each bit represents a CPU. How the system's CPUs are mapped to bits in the bitset is system dependent. -The data type has a fixed size; in the unlikely case that the number -of bits are not sufficient to describe the CPUs of the system a -different interface has to be used. +The data type has a fixed size; it is strongly recommended to allocate +a dynamically sized set based on the actual number of CPUs detected, +such as via @code{get_nprocs()}, and use the @code{CPU_*_S} variants +instead of the fixed-size ones. This type is a GNU extension and is defined in @file{sched.h}. @end deftp -To manipulate the bitset, to set and reset bits, a number of macros are -defined. Some of the macros take a CPU number as a parameter. Here -it is important to never exceed the size of the bitset. The following -macro specifies the number of bits in the @code{cpu_set_t} bitset. +To manipulate the bitset, to set and reset bits, and thus add and +remove CPUs from the sets, a number of macros are defined. Some of +the macros take a CPU number as a parameter. Here it is important to +never exceed the size of the bitset, either @code{CPU_SETSIZE} for +fixed sets or the allocated size for dynamic sets. For each macro +there is a fixed-size version (documented below) and a dynamic-sized +version (with a @code{_S} suffix). @deftypevr Macro int CPU_SETSIZE @standards{GNU, sched.h} The value of this macro is the maximum number of CPUs which can be -handled with a @code{cpu_set_t} object. +handled with a fixed @code{cpu_set_t} object. @end deftypevr +For applications that require CPU sets larger than the built-in size, +a set of macros that support dynamically-sized sets are defined. + +@deftypefn Macro size_t CPU_ALLOC_SIZE (size_t @var{count}) +@standards{GNU, sched.h} +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +@c CPU_ALLOC_SIZE ok +@c __CPU_ALLOC_SIZE ok +Given a count of CPUs to hold, returns the size of the set to +allocate. This return value is appropriate to be used in the *_S macros. + +This macro is a GNU extension and is defined in @file{sched.h}. +@end deftypefn + +@deftypefn Macro {cpu_set_t *} CPU_ALLOC (size_t @var{count}) +@standards{GNU, sched.h} +@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}} +@c CPU_ALLOC +@c __CPU_ALLOC +@c __sched_cpualloc +@c malloc +Given the count of CPUs to hold, returns a set large enough to hold +them; that is, the resulting set will be valid for CPUs numbered 0 +through @var{count}-1, inclusive. This set must be freed via +@code{CPU_FREE} to avoid memory leaks. Warning: the argument is the +CPU @emph{count} and not the size returned by @code{CPU_ALLOC_SIZE}. + +This macro is a GNU extension and is defined in @file{sched.h}. +@end deftypefn + +@deftypefn Macro void CPU_FREE (cpu_set_t *@var{set}) +@standards{GNU, sched.h} +@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}} +@c CPU_FREE +@c __CPU_FREE +@c __sched_cpufree +@c free +Frees a CPU set previously allocated by @code{CPU_ALLOC}. + +This macro is a GNU extension and is defined in @file{sched.h}. +@end deftypefn + The type @code{cpu_set_t} should be considered opaque; all -manipulation should happen via the next four macros. +manipulation should happen via the @code{CPU_*} macros described +below. @deftypefn Macro void CPU_ZERO (cpu_set_t *@var{set}) @standards{GNU, sched.h} @@ -1424,6 +1471,39 @@ evaluated more than once. This macro is a GNU extension and is defined in @file{sched.h}. @end deftypefn +@deftypefn Macro {cpu_set_t *} CPU_AND (cpu_set_t *@var{dest}, cpu_set_t *@var{src1}, cpu_set_t *@var{src2}) +@standards{GNU, sched.h} +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +@c CPU_AND ok +@c __CPU_OP_S ok +This macro populates @var{dest} with only those CPUs included in both +@var{src1} and @var{src2}. Its value is @var{dest}. + +This macro is a GNU extension and is defined in @file{sched.h}. +@end deftypefn + +@deftypefn Macro {cpu_set_t *} CPU_OR (cpu_set_t *@var{dest}, cpu_set_t *@var{src1}, cpu_set_t *@var{src2}) +@standards{GNU, sched.h} +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +@c CPU_OR ok +@c __CPU_OP_S ok +This macro populates @var{dest} with those CPUs included in either +@var{src1} or @var{src2}. Its value is @var{dest}. + +This macro is a GNU extension and is defined in @file{sched.h}. +@end deftypefn + +@deftypefn Macro {cpu_set_t *} CPU_XOR (cpu_set_t *@var{dest}, cpu_set_t *@var{src1}, cpu_set_t *@var{src2}) +@standards{GNU, sched.h} +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +@c CPU_XOR ok +@c __CPU_OP_S ok +This macro populates @var{dest} with those CPUs included in either +@var{src1} or @var{src2}, but not both. Its value is @var{dest}. + +This macro is a GNU extension and is defined in @file{sched.h}. +@end deftypefn + @deftypefn Macro int CPU_ISSET (int @var{cpu}, const cpu_set_t *@var{set}) @standards{GNU, sched.h} @safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} @@ -1440,6 +1520,54 @@ evaluated more than once. This macro is a GNU extension and is defined in @file{sched.h}. @end deftypefn +@deftypefn Macro int CPU_COUNT (const cpu_set_t *@var{set}) +@standards{GNU, sched.h} +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +@c CPU_COUNT ok +@c __CPU_COUNT_S ok +@c __sched_cpucount ok +@c countbits ok +This macro returns the count of CPUs (bits) set in @var{set}. + +This macro is a GNU extension and is defined in @file{sched.h}. +@end deftypefn + +@deftypefn Macro int CPU_EQUAL (cpu_set_t *@var{src1}, cpu_set_t *@var{src2}) +@standards{GNU, sched.h} +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +@c CPU_EQUAL ok +@c __CPU_EQUAL_S ok +@c memcmp ok +This macro returns nonzero if the two sets @var{set1} and @var{set2} +have the same contents; that is, the set of CPUs represented by both +sets is identical. + +This macro is a GNU extension and is defined in @file{sched.h}. +@end deftypefn + +@deftypefn Macro void CPU_ZERO_S (size_t @var{size}, cpu_set_t *@var{set}) +@end deftypefn +@deftypefn Macro void CPU_SET_S (int @var{cpu}, size_t @var{size}, cpu_set_t *@var{set}) +@end deftypefn +@deftypefn Macro void CPU_CLR_S (int @var{cpu}, size_t @var{size}, cpu_set_t *@var{set}) +@end deftypefn +@deftypefn Macro {cpu_set_t *} CPU_AND_S (size_t @var{size}, cpu_set_t *@var{dest}, cpu_set_t *@var{src1}, cpu_set_t *@var{src2}) +@end deftypefn +@deftypefn Macro {cpu_set_t *} CPU_OR_S (size_t @var{size}, cpu_set_t *@var{dest}, cpu_set_t *@var{src1}, cpu_set_t *@var{src2}) +@end deftypefn +@deftypefn Macro {cpu_set_t *} CPU_XOR_S (size_t @var{size}, cpu_set_t *@var{dest}, cpu_set_t *@var{src1}, cpu_set_t *@var{src2}) +@end deftypefn +@deftypefn Macro int CPU_ISSET_S (int @var{cpu}, size_t @var{size}, const cpu_set_t *@var{set}) +@end deftypefn +@deftypefn Macro int CPU_COUNT_S (size_t @var{size}, const cpu_set_t *@var{set}) +@end deftypefn +@deftypefn Macro int CPU_EQUAL_S (size_t @var{size}, cpu_set_t *@var{src1}, cpu_set_t *@var{src2}) +@end deftypefn + +Each of these macros performs the same action as its non-@code{_S} variant, +but takes a @var{size} argument to specify the set size. This +@var{size} argument is as returned by the @code{CPU_ALLOC_SIZE} macro, +defined above. CPU bitsets can be constructed from scratch or the currently installed affinity mask can be retrieved from the system. @@ -1525,6 +1653,33 @@ The operating system does not support this function. This function is Linux-specific and is declared in @file{sched.h}. @end deftypefun +Here's an example of how to use most of the above to limit the number +of CPUs a process runs on, not including error handling or good logic +on CPU choices: + +@example +#include +void limit_cpus (void) +@{ + unsigned int mycpu; + size_t nproc, cssz, cpu; + cpu_set_t *cs, *cs1; + getcpu (&mycpu, NULL); + nproc = get_nprocs (); + cssz = CPU_ALLOC_SIZE (nproc); + cs = CPU_ALLOC (nproc); + sched_getaffinity (getpid(), cssz, cs1); + if (CPU_COUNT_S (cssz, cs1) > nproc / 2) + @{ + for (cpu = nproc / 2; cpu < nproc; cpu ++) + if (cpu != mycpu) + CPU_CLR_S (cpu, cssz, cs); + sched_setaffinity (getpid(), cssz, cs1); + @} + CPU_FREE (cs); +@} +@end example + @node Memory Resources @section Querying memory available resources