162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci/* Do not include this file directly. */ 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#ifndef _TRACE_INTERNAL_PID_LIST_H 662306a36Sopenharmony_ci#define _TRACE_INTERNAL_PID_LIST_H 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci/* 962306a36Sopenharmony_ci * In order to keep track of what pids to trace, a tree is created much 1062306a36Sopenharmony_ci * like page tables are used. This creates a sparse bit map, where 1162306a36Sopenharmony_ci * the tree is filled in when needed. A PID is at most 30 bits (see 1262306a36Sopenharmony_ci * linux/thread.h), and is broken up into 3 sections based on the bit map 1362306a36Sopenharmony_ci * of the bits. The 8 MSB is the "upper1" section. The next 8 MSB is the 1462306a36Sopenharmony_ci * "upper2" section and the 14 LSB is the "lower" section. 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * A trace_pid_list structure holds the "upper1" section, in an 1762306a36Sopenharmony_ci * array of 256 pointers (1 or 2K in size) to "upper_chunk" unions, where 1862306a36Sopenharmony_ci * each has an array of 256 pointers (1 or 2K in size) to the "lower_chunk" 1962306a36Sopenharmony_ci * structures, where each has an array of size 2K bytes representing a bitmask 2062306a36Sopenharmony_ci * of the 14 LSB of the PID (256 * 8 = 2048) 2162306a36Sopenharmony_ci * 2262306a36Sopenharmony_ci * When a trace_pid_list is allocated, it includes the 256 pointer array 2362306a36Sopenharmony_ci * of the upper1 unions. Then a "cache" of upper and lower is allocated 2462306a36Sopenharmony_ci * where these will be assigned as needed. 2562306a36Sopenharmony_ci * 2662306a36Sopenharmony_ci * When a bit is set in the pid_list bitmask, the pid to use has 2762306a36Sopenharmony_ci * the 8 MSB masked, and this is used to index the array in the 2862306a36Sopenharmony_ci * pid_list to find the next upper union. If the element is NULL, 2962306a36Sopenharmony_ci * then one is retrieved from the upper_list cache. If none is 3062306a36Sopenharmony_ci * available, then -ENOMEM is returned. 3162306a36Sopenharmony_ci * 3262306a36Sopenharmony_ci * The next 8 MSB is used to index into the "upper2" section. If this 3362306a36Sopenharmony_ci * element is NULL, then it is retrieved from the lower_list cache. 3462306a36Sopenharmony_ci * Again, if one is not available -ENOMEM is returned. 3562306a36Sopenharmony_ci * 3662306a36Sopenharmony_ci * Finally the 14 LSB of the PID is used to set the bit in the 16384 3762306a36Sopenharmony_ci * bitmask (made up of 2K bytes). 3862306a36Sopenharmony_ci * 3962306a36Sopenharmony_ci * When the second upper section or the lower section has their last 4062306a36Sopenharmony_ci * bit cleared, they are added back to the free list to be reused 4162306a36Sopenharmony_ci * when needed. 4262306a36Sopenharmony_ci */ 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#define UPPER_BITS 8 4562306a36Sopenharmony_ci#define UPPER_MAX (1 << UPPER_BITS) 4662306a36Sopenharmony_ci#define UPPER1_SIZE (1 << UPPER_BITS) 4762306a36Sopenharmony_ci#define UPPER2_SIZE (1 << UPPER_BITS) 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci#define LOWER_BITS 14 5062306a36Sopenharmony_ci#define LOWER_MAX (1 << LOWER_BITS) 5162306a36Sopenharmony_ci#define LOWER_SIZE (LOWER_MAX / BITS_PER_LONG) 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci#define UPPER1_SHIFT (LOWER_BITS + UPPER_BITS) 5462306a36Sopenharmony_ci#define UPPER2_SHIFT LOWER_BITS 5562306a36Sopenharmony_ci#define LOWER_MASK (LOWER_MAX - 1) 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci#define UPPER_MASK (UPPER_MAX - 1) 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci/* According to linux/thread.h pids can not be bigger than or equal to 1 << 30 */ 6062306a36Sopenharmony_ci#define MAX_PID (1 << 30) 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci/* Just keep 6 chunks of both upper and lower in the cache on alloc */ 6362306a36Sopenharmony_ci#define CHUNK_ALLOC 6 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci/* Have 2 chunks free, trigger a refill of the cache */ 6662306a36Sopenharmony_ci#define CHUNK_REALLOC 2 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ciunion lower_chunk { 6962306a36Sopenharmony_ci union lower_chunk *next; 7062306a36Sopenharmony_ci unsigned long data[LOWER_SIZE]; // 2K in size 7162306a36Sopenharmony_ci}; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ciunion upper_chunk { 7462306a36Sopenharmony_ci union upper_chunk *next; 7562306a36Sopenharmony_ci union lower_chunk *data[UPPER2_SIZE]; // 1 or 2K in size 7662306a36Sopenharmony_ci}; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_cistruct trace_pid_list { 7962306a36Sopenharmony_ci raw_spinlock_t lock; 8062306a36Sopenharmony_ci struct irq_work refill_irqwork; 8162306a36Sopenharmony_ci union upper_chunk *upper[UPPER1_SIZE]; // 1 or 2K in size 8262306a36Sopenharmony_ci union upper_chunk *upper_list; 8362306a36Sopenharmony_ci union lower_chunk *lower_list; 8462306a36Sopenharmony_ci int free_upper_chunks; 8562306a36Sopenharmony_ci int free_lower_chunks; 8662306a36Sopenharmony_ci}; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci#endif /* _TRACE_INTERNAL_PID_LIST_H */ 89