kernel: Use anonymous namespaces to avoid type collisions.

The anonymous namespace makes type definitions local to the translation
unit (like static does for objects). For pretty much any type not shared
across multiple files this is what one wants to happen (and might
erroneously expect to happen automatically).

This commit solves some actual collisions that were present:

* The VFS and the rootfs both used an incompatible VnodeHash struct for
  their BOpenHashTable.
* XSI semaphores and message queues both used queued_thread, Ipc and
  IpcHashTableDefinition.

For release builds these did not cause problems as the types were fully
inlined. Debug builds would crash at boot however because parts of a
BOpenHashTable<VnodeHash> from the rootfs meant to operate on struct
rootfs_vnode would be applied to one from the VFS expecting struct
vnode.

As such collisions are violations of the one definition rule, the code
is at fault and unfortunatley the compiler isn't required to diagnose
such problems across translation units (which isn't actually trivial).
This can lead to subtle and hard to debug problems and it's therefore
best to avoid leaking types into the global namespace whenever possible.
This commit is contained in:
Michael Lotz
2015-11-08 22:31:56 +01:00
parent c6fb0e2c4d
commit c73d13015d
15 changed files with 154 additions and 81 deletions
+5
View File
@@ -59,6 +59,8 @@
void *gDmaAddress; void *gDmaAddress;
namespace {
struct memory_type_range : DoublyLinkedListLinkImpl<memory_type_range> { struct memory_type_range : DoublyLinkedListLinkImpl<memory_type_range> {
uint64 base; uint64 base;
uint64 size; uint64 size;
@@ -89,6 +91,9 @@ struct update_mtrr_info {
typedef DoublyLinkedList<memory_type_range> MemoryTypeRangeList; typedef DoublyLinkedList<memory_type_range> MemoryTypeRangeList;
} // namespace
static mutex sMemoryTypeLock = MUTEX_INITIALIZER("memory type ranges"); static mutex sMemoryTypeLock = MUTEX_INITIALIZER("memory type ranges");
static MemoryTypeRangeList sMemoryTypeRanges; static MemoryTypeRangeList sMemoryTypeRanges;
static int32 sMemoryTypeRangeCount = 0; static int32 sMemoryTypeRangeCount = 0;
+4
View File
@@ -50,6 +50,8 @@ static const bigtime_t kTransactionIdleTime = 2000000LL;
// a transaction is considered idle after 2 seconds of inactivity // a transaction is considered idle after 2 seconds of inactivity
namespace {
struct cache_transaction; struct cache_transaction;
struct cached_block; struct cached_block;
struct block_cache; struct block_cache;
@@ -322,6 +324,8 @@ public:
typedef AutoLocker<block_cache, TransactionLocking> TransactionLocker; typedef AutoLocker<block_cache, TransactionLocking> TransactionLocker;
} // namespace
#if BLOCK_CACHE_BLOCK_TRACING && !defined(BUILDING_USERLAND_FS_SERVER) #if BLOCK_CACHE_BLOCK_TRACING && !defined(BUILDING_USERLAND_FS_SERVER)
namespace BlockTracing { namespace BlockTracing {
+7 -5
View File
@@ -50,6 +50,8 @@
#endif #endif
namespace {
struct devfs_partition { struct devfs_partition {
struct devfs_vnode* raw_device; struct devfs_vnode* raw_device;
partition_info info; partition_info info;
@@ -158,11 +160,11 @@ enum {
ITERATION_STATE_BEGIN = ITERATION_STATE_DOT, ITERATION_STATE_BEGIN = ITERATION_STATE_DOT,
}; };
// extern and in a private namespace only to make forward declaration possible // extern only to make forward declaration possible
namespace { extern fs_volume_ops kVolumeOps;
extern fs_volume_ops kVolumeOps; extern fs_vnode_ops kVnodeOps;
extern fs_vnode_ops kVnodeOps;
} } // namespace
static status_t get_node_for_path(struct devfs* fs, const char* path, static status_t get_node_for_path(struct devfs* fs, const char* path,
@@ -219,27 +219,6 @@ public:
}; };
} // unnamed namespace
static status_t unload_driver(legacy_driver *driver);
static status_t load_driver(legacy_driver *driver);
static DriverWatcher sDriverWatcher;
static int32 sDriverEventsPending;
static DriverEventList sDriverEvents;
static mutex sDriverEventsLock = MUTEX_INITIALIZER("driver events");
// inner lock, protects the sDriverEvents list only
static DirectoryWatcher sDirectoryWatcher;
static DirectoryNodeHash sDirectoryNodeHash;
static recursive_lock sLock;
static bool sWatching;
// #pragma mark - driver private
struct DriverHash { struct DriverHash {
typedef const char* KeyType; typedef const char* KeyType;
typedef legacy_driver ValueType; typedef legacy_driver ValueType;
@@ -268,9 +247,29 @@ struct DriverHash {
typedef BOpenHashTable<DriverHash> DriverTable; typedef BOpenHashTable<DriverHash> DriverTable;
} // unnamed namespace
static status_t unload_driver(legacy_driver *driver);
static status_t load_driver(legacy_driver *driver);
static DriverWatcher sDriverWatcher;
static int32 sDriverEventsPending;
static DriverEventList sDriverEvents;
static mutex sDriverEventsLock = MUTEX_INITIALIZER("driver events");
// inner lock, protects the sDriverEvents list only
static DirectoryWatcher sDirectoryWatcher;
static DirectoryNodeHash sDirectoryNodeHash;
static recursive_lock sLock;
static bool sWatching;
static DriverTable* sDriverHash; static DriverTable* sDriverHash;
// #pragma mark - driver private
/*! Collects all published devices of a driver, compares them to what the /*! Collects all published devices of a driver, compares them to what the
driver would publish now, and then publishes/unpublishes the devices driver would publish now, and then publishes/unpublishes the devices
as needed. as needed.
+5
View File
@@ -53,6 +53,8 @@
#endif #endif
namespace {
#define IMAGE_HASH_SIZE 16 #define IMAGE_HASH_SIZE 16
struct ImageHashDefinition { struct ImageHashDefinition {
@@ -77,6 +79,9 @@ struct ImageHashDefinition {
typedef BOpenHashTable<ImageHashDefinition> ImageHash; typedef BOpenHashTable<ImageHashDefinition> ImageHash;
} // namespace
static ImageHash *sImagesHash; static ImageHash *sImagesHash;
static struct elf_image_info *sKernelImage = NULL; static struct elf_image_info *sKernelImage = NULL;
+9 -5
View File
@@ -46,6 +46,8 @@
#endif #endif
namespace {
struct rootfs_stream { struct rootfs_stream {
mode_t type; mode_t type;
struct stream_dir { struct stream_dir {
@@ -124,11 +126,13 @@ enum {
ITERATION_STATE_BEGIN = ITERATION_STATE_DOT, ITERATION_STATE_BEGIN = ITERATION_STATE_DOT,
}; };
// extern and in a private namespace only to make forward declaration possible
namespace { // extern only to make forward declaration possible
extern fs_volume_ops sVolumeOps; extern fs_volume_ops sVolumeOps;
extern fs_vnode_ops sVnodeOps; extern fs_vnode_ops sVnodeOps;
}
} // namespace
#define ROOTFS_HASH_SIZE 16 #define ROOTFS_HASH_SIZE 16
+19 -6
View File
@@ -111,11 +111,6 @@ const static size_t kMaxPathLength = 65536;
// on PATH_MAX // on PATH_MAX
struct vnode_hash_key {
dev_t device;
ino_t vnode;
};
typedef DoublyLinkedList<vnode> VnodeList; typedef DoublyLinkedList<vnode> VnodeList;
/*! \brief Structure to manage a mounted file system /*! \brief Structure to manage a mounted file system
@@ -171,6 +166,9 @@ struct fs_mount {
bool owns_file_device; bool owns_file_device;
}; };
namespace {
struct advisory_lock : public DoublyLinkedListLinkImpl<advisory_lock> { struct advisory_lock : public DoublyLinkedListLinkImpl<advisory_lock> {
list_link link; list_link link;
team_id team; team_id team;
@@ -182,6 +180,9 @@ struct advisory_lock : public DoublyLinkedListLinkImpl<advisory_lock> {
typedef DoublyLinkedList<advisory_lock> LockList; typedef DoublyLinkedList<advisory_lock> LockList;
} // namespace
struct advisory_locking { struct advisory_locking {
sem_id lock; sem_id lock;
sem_id wait_sem; sem_id wait_sem;
@@ -251,6 +252,13 @@ static rw_lock sVnodeLock = RW_LOCK_INITIALIZER("vfs_vnode_lock");
static mutex sIOContextRootLock = MUTEX_INITIALIZER("io_context::root lock"); static mutex sIOContextRootLock = MUTEX_INITIALIZER("io_context::root lock");
namespace {
struct vnode_hash_key {
dev_t device;
ino_t vnode;
};
struct VnodeHash { struct VnodeHash {
typedef vnode_hash_key KeyType; typedef vnode_hash_key KeyType;
typedef struct vnode ValueType; typedef struct vnode ValueType;
@@ -311,6 +319,8 @@ struct MountHash {
typedef BOpenHashTable<MountHash> MountTable; typedef BOpenHashTable<MountHash> MountTable;
} // namespace
#define VNODE_HASH_TABLE_SIZE 1024 #define VNODE_HASH_TABLE_SIZE 1024
static VnodeTable* sVnodeTable; static VnodeTable* sVnodeTable;
@@ -520,7 +530,8 @@ static struct fd_ops sQueryOps = {
}; };
// VNodePutter namespace {
class VNodePutter { class VNodePutter {
public: public:
VNodePutter(struct vnode* vnode = NULL) : fVNode(vnode) {} VNodePutter(struct vnode* vnode = NULL) : fVNode(vnode) {}
@@ -597,6 +608,8 @@ private:
bool fKernel; bool fKernel;
}; };
} // namespace
#if VFS_PAGES_IO_TRACING #if VFS_PAGES_IO_TRACING
+4
View File
@@ -33,6 +33,8 @@
#define ADD_DEBUGGER_COMMANDS #define ADD_DEBUGGER_COMMANDS
namespace {
struct ImageTableDefinition { struct ImageTableDefinition {
typedef image_id KeyType; typedef image_id KeyType;
typedef struct image ValueType; typedef struct image ValueType;
@@ -68,6 +70,8 @@ public:
} }
}; };
} // namespace
static image_id sNextImageID = 1; static image_id sNextImageID = 1;
static mutex sImageMutex = MUTEX_INITIALIZER("image"); static mutex sImageMutex = MUTEX_INITIALIZER("image");
+39 -39
View File
@@ -275,45 +275,6 @@ private:
NotificationList fNotifications; NotificationList fNotifications;
}; };
} // namespace Module
using namespace Module;
/* These are the standard base paths where we start to look for modules
* to load. Order is important, the last entry here will be searched
* first.
*/
static const directory_which kModulePaths[] = {
B_BEOS_ADDONS_DIRECTORY,
B_SYSTEM_NONPACKAGED_ADDONS_DIRECTORY,
B_USER_ADDONS_DIRECTORY,
B_USER_NONPACKAGED_ADDONS_DIRECTORY,
};
static const uint32 kNumModulePaths = sizeof(kModulePaths)
/ sizeof(kModulePaths[0]);
static const uint32 kFirstNonSystemModulePath = 1;
static ModuleNotificationService sModuleNotificationService;
static bool sDisableUserAddOns = false;
/* Locking scheme: There is a global lock only; having several locks
makes trouble if dependent modules get loaded concurrently ->
they have to wait for each other, i.e. we need one lock per module;
also we must detect circular references during init and not dead-lock.
Reference counting: get_module() increments the ref count of a module,
put_module() decrements it. When a B_KEEP_LOADED module is initialized
the ref count is incremented once more, so it never gets
uninitialized/unloaded. A referenced module, unless it's built-in, has a
non-null module_image and owns a reference to the image. When the last
module reference is put, the image's reference is released and module_image
zeroed (as long as the boot volume has not been mounted, it is not zeroed).
An unreferenced module image is unloaded (when the boot volume is mounted).
*/
static recursive_lock sModulesLock;
struct ModuleHash { struct ModuleHash {
typedef const char* KeyType; typedef const char* KeyType;
@@ -364,6 +325,45 @@ struct ImageHash {
typedef BOpenHashTable<ImageHash> ImageTable; typedef BOpenHashTable<ImageHash> ImageTable;
} // namespace Module
using namespace Module;
/* These are the standard base paths where we start to look for modules
* to load. Order is important, the last entry here will be searched
* first.
*/
static const directory_which kModulePaths[] = {
B_BEOS_ADDONS_DIRECTORY,
B_SYSTEM_NONPACKAGED_ADDONS_DIRECTORY,
B_USER_ADDONS_DIRECTORY,
B_USER_NONPACKAGED_ADDONS_DIRECTORY,
};
static const uint32 kNumModulePaths = sizeof(kModulePaths)
/ sizeof(kModulePaths[0]);
static const uint32 kFirstNonSystemModulePath = 1;
static ModuleNotificationService sModuleNotificationService;
static bool sDisableUserAddOns = false;
/* Locking scheme: There is a global lock only; having several locks
makes trouble if dependent modules get loaded concurrently ->
they have to wait for each other, i.e. we need one lock per module;
also we must detect circular references during init and not dead-lock.
Reference counting: get_module() increments the ref count of a module,
put_module() decrements it. When a B_KEEP_LOADED module is initialized
the ref count is incremented once more, so it never gets
uninitialized/unloaded. A referenced module, unless it's built-in, has a
non-null module_image and owns a reference to the image. When the last
module reference is put, the image's reference is released and module_image
zeroed (as long as the boot volume has not been mounted, it is not zeroed).
An unreferenced module image is unloaded (when the boot volume is mounted).
*/
static recursive_lock sModulesLock;
/* We store the loaded modules by directory path, and all known modules /* We store the loaded modules by directory path, and all known modules
* by module name in a hash table for quick access * by module name in a hash table for quick access
+10 -5
View File
@@ -86,11 +86,7 @@
// has a reference to a deleted port. // has a reference to a deleted port.
struct port_message; namespace {
static void put_port_message(port_message* message);
struct port_message : DoublyLinkedListLinkImpl<port_message> { struct port_message : DoublyLinkedListLinkImpl<port_message> {
int32 code; int32 code;
@@ -103,6 +99,13 @@ struct port_message : DoublyLinkedListLinkImpl<port_message> {
typedef DoublyLinkedList<port_message> MessageList; typedef DoublyLinkedList<port_message> MessageList;
} // namespace
static void put_port_message(port_message* message);
namespace {
struct Port : public KernelReferenceable { struct Port : public KernelReferenceable {
enum State { enum State {
@@ -233,6 +236,8 @@ public:
void Notify(uint32 opcode, port_id team); void Notify(uint32 opcode, port_id team);
}; };
} // namespace
// #pragma mark - tracing // #pragma mark - tracing
+4
View File
@@ -24,6 +24,8 @@
#include <util/StringHash.h> #include <util/StringHash.h>
namespace {
class SemInfo { class SemInfo {
public: public:
SemInfo() SemInfo()
@@ -364,6 +366,8 @@ struct TeamSemHashDefinition {
} }
}; };
} // namespace
struct realtime_sem_context { struct realtime_sem_context {
realtime_sem_context() realtime_sem_context()
@@ -33,6 +33,9 @@
# define TRACE_ERROR(x) dprintf x # define TRACE_ERROR(x) dprintf x
#endif #endif
namespace {
// Queue for holding blocked threads // Queue for holding blocked threads
struct queued_thread : DoublyLinkedListLinkImpl<queued_thread> { struct queued_thread : DoublyLinkedListLinkImpl<queued_thread> {
queued_thread(Thread *_thread, int32 _message_length) queued_thread(Thread *_thread, int32 _message_length)
@@ -374,6 +377,9 @@ struct IpcHashTableDefinition {
} }
}; };
} // namespace
// Arbitrary limits // Arbitrary limits
#define MAX_XSI_MESSAGE 4096 #define MAX_XSI_MESSAGE 4096
#define MAX_XSI_MESSAGE_QUEUE 1024 #define MAX_XSI_MESSAGE_QUEUE 1024
+13
View File
@@ -34,6 +34,9 @@
# define TRACE_ERROR(x) dprintf x # define TRACE_ERROR(x) dprintf x
#endif #endif
namespace {
// Queue for holding blocked threads // Queue for holding blocked threads
struct queued_thread : DoublyLinkedListLinkImpl<queued_thread> { struct queued_thread : DoublyLinkedListLinkImpl<queued_thread> {
queued_thread(Thread *thread, int32 count) queued_thread(Thread *thread, int32 count)
@@ -72,6 +75,10 @@ typedef DoublyLinkedList<sem_undo> UndoList;
typedef DoublyLinkedList<sem_undo, typedef DoublyLinkedList<sem_undo,
DoublyLinkedListMemberGetLink<sem_undo, &sem_undo::team_link> > TeamList; DoublyLinkedListMemberGetLink<sem_undo, &sem_undo::team_link> > TeamList;
} // namespace
// Forward declared in global namespace.
struct xsi_sem_context { struct xsi_sem_context {
xsi_sem_context() xsi_sem_context()
{ {
@@ -87,6 +94,9 @@ struct xsi_sem_context {
mutex lock; mutex lock;
}; };
namespace {
// Xsi semaphore definition // Xsi semaphore definition
class XsiSemaphore { class XsiSemaphore {
public: public:
@@ -621,6 +631,9 @@ struct IpcHashTableDefinition {
} }
}; };
} // namespace
// Arbitrary limit // Arbitrary limit
#define MAX_XSI_SEMAPHORE 4096 #define MAX_XSI_SEMAPHORE 4096
#define MAX_XSI_SEMAPHORE_SET 2048 #define MAX_XSI_SEMAPHORE_SET 2048
+5
View File
@@ -42,6 +42,8 @@
// #pragma mark - AddressSpaceHashDefinition // #pragma mark - AddressSpaceHashDefinition
namespace {
struct AddressSpaceHashDefinition { struct AddressSpaceHashDefinition {
typedef team_id KeyType; typedef team_id KeyType;
typedef VMAddressSpace ValueType; typedef VMAddressSpace ValueType;
@@ -69,6 +71,9 @@ struct AddressSpaceHashDefinition {
typedef BOpenHashTable<AddressSpaceHashDefinition> AddressSpaceTable; typedef BOpenHashTable<AddressSpaceHashDefinition> AddressSpaceTable;
} // namespace
static AddressSpaceTable sAddressSpaceTable; static AddressSpaceTable sAddressSpaceTable;
static rw_lock sAddressSpaceTableLock; static rw_lock sAddressSpaceTableLock;
+4
View File
@@ -73,6 +73,8 @@
#endif #endif
namespace {
class AreaCacheLocking { class AreaCacheLocking {
public: public:
inline bool Lock(VMCache* lockable) inline bool Lock(VMCache* lockable)
@@ -229,6 +231,8 @@ private:
VMCache* fBottomCache; VMCache* fBottomCache;
}; };
} // namespace
// The memory reserve an allocation of the certain priority must not touch. // The memory reserve an allocation of the certain priority must not touch.
static const size_t kMemoryReserveForPriority[] = { static const size_t kMemoryReserveForPriority[] = {