mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-28 20:02:17 +00:00
![Andi Kleen](/assets/img/avatar_default.png)
There was some desire in large applications using MAP_HUGETLB or SHM_HUGETLB to use 1GB huge pages on some mappings, and stay with 2MB on others. This is useful together with NUMA policy: use 2MB interleaving on some mappings, but 1GB on local mappings. This patch extends the IPC/SHM syscall interfaces slightly to allow specifying the page size. It borrows some upper bits in the existing flag arguments and allows encoding the log of the desired page size in addition to the *_HUGETLB flag. When 0 is specified the default size is used, this makes the change fully compatible. Extending the internal hugetlb code to handle this is straight forward. Instead of a single mount it just keeps an array of them and selects the right mount based on the specified page size. When no page size is specified it uses the mount of the default page size. The change is not visible in /proc/mounts because internal mounts don't appear there. It also has very little overhead: the additional mounts just consume a super block, but not more memory when not used. I also exported the new flags to the user headers (they were previously under __KERNEL__). Right now only symbols for x86 and some other architecture for 1GB and 2MB are defined. The interface should already work for all other architectures though. Only architectures that define multiple hugetlb sizes actually need it (that is currently x86, tile, powerpc). However tile and powerpc have user configurable hugetlb sizes, so it's not easy to add defines. A program on those architectures would need to query sysfs and use the appropiate log2. [akpm@linux-foundation.org: cleanups] [rientjes@google.com: fix build] [akpm@linux-foundation.org: checkpatch fixes] Signed-off-by: Andi Kleen <ak@linux.intel.com> Cc: Michael Kerrisk <mtk.manpages@gmail.com> Acked-by: Rik van Riel <riel@redhat.com> Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Hillf Danton <dhillf@gmail.com> Signed-off-by: David Rientjes <rientjes@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
68 lines
1.9 KiB
C
68 lines
1.9 KiB
C
#ifndef _LINUX_SHM_H_
|
|
#define _LINUX_SHM_H_
|
|
|
|
#include <asm/page.h>
|
|
#include <uapi/linux/shm.h>
|
|
|
|
#define SHMALL (SHMMAX/PAGE_SIZE*(SHMMNI/16)) /* max shm system wide (pages) */
|
|
#include <asm/shmparam.h>
|
|
struct shmid_kernel /* private to the kernel */
|
|
{
|
|
struct kern_ipc_perm shm_perm;
|
|
struct file * shm_file;
|
|
unsigned long shm_nattch;
|
|
unsigned long shm_segsz;
|
|
time_t shm_atim;
|
|
time_t shm_dtim;
|
|
time_t shm_ctim;
|
|
pid_t shm_cprid;
|
|
pid_t shm_lprid;
|
|
struct user_struct *mlock_user;
|
|
|
|
/* The task created the shm object. NULL if the task is dead. */
|
|
struct task_struct *shm_creator;
|
|
};
|
|
|
|
/* shm_mode upper byte flags */
|
|
#define SHM_DEST 01000 /* segment will be destroyed on last detach */
|
|
#define SHM_LOCKED 02000 /* segment will not be swapped */
|
|
#define SHM_HUGETLB 04000 /* segment will use huge TLB pages */
|
|
#define SHM_NORESERVE 010000 /* don't check for reservations */
|
|
|
|
/* Bits [26:31] are reserved */
|
|
|
|
/*
|
|
* When SHM_HUGETLB is set bits [26:31] encode the log2 of the huge page size.
|
|
* This gives us 6 bits, which is enough until someone invents 128 bit address
|
|
* spaces.
|
|
*
|
|
* Assume these are all power of twos.
|
|
* When 0 use the default page size.
|
|
*/
|
|
#define SHM_HUGE_SHIFT 26
|
|
#define SHM_HUGE_MASK 0x3f
|
|
#define SHM_HUGE_2MB (21 << SHM_HUGE_SHIFT)
|
|
#define SHM_HUGE_1GB (30 << SHM_HUGE_SHIFT)
|
|
|
|
#ifdef CONFIG_SYSVIPC
|
|
long do_shmat(int shmid, char __user *shmaddr, int shmflg, unsigned long *addr,
|
|
unsigned long shmlba);
|
|
extern int is_file_shm_hugepages(struct file *file);
|
|
extern void exit_shm(struct task_struct *task);
|
|
#else
|
|
static inline long do_shmat(int shmid, char __user *shmaddr,
|
|
int shmflg, unsigned long *addr,
|
|
unsigned long shmlba)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
static inline int is_file_shm_hugepages(struct file *file)
|
|
{
|
|
return 0;
|
|
}
|
|
static inline void exit_shm(struct task_struct *task)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
#endif /* _LINUX_SHM_H_ */
|