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;
namespace {
struct memory_type_range : DoublyLinkedListLinkImpl<memory_type_range> {
uint64 base;
uint64 size;
@@ -89,6 +91,9 @@ struct update_mtrr_info {
typedef DoublyLinkedList<memory_type_range> MemoryTypeRangeList;
} // namespace
static mutex sMemoryTypeLock = MUTEX_INITIALIZER("memory type ranges");
static MemoryTypeRangeList sMemoryTypeRanges;
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
namespace {
struct cache_transaction;
struct cached_block;
struct block_cache;
@@ -322,6 +324,8 @@ public:
typedef AutoLocker<block_cache, TransactionLocking> TransactionLocker;
} // namespace
#if BLOCK_CACHE_BLOCK_TRACING && !defined(BUILDING_USERLAND_FS_SERVER)
namespace BlockTracing {
+7 -5
View File
@@ -50,6 +50,8 @@
#endif
namespace {
struct devfs_partition {
struct devfs_vnode* raw_device;
partition_info info;
@@ -158,11 +160,11 @@ enum {
ITERATION_STATE_BEGIN = ITERATION_STATE_DOT,
};
// extern and in a private namespace only to make forward declaration possible
namespace {
extern fs_volume_ops kVolumeOps;
extern fs_vnode_ops kVnodeOps;
}
// extern only to make forward declaration possible
extern fs_volume_ops kVolumeOps;
extern fs_vnode_ops kVnodeOps;
} // namespace
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 {
typedef const char* KeyType;
typedef legacy_driver ValueType;
@@ -268,9 +247,29 @@ struct DriverHash {
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;
// #pragma mark - driver private
/*! Collects all published devices of a driver, compares them to what the
driver would publish now, and then publishes/unpublishes the devices
as needed.
+5
View File
@@ -53,6 +53,8 @@
#endif
namespace {
#define IMAGE_HASH_SIZE 16
struct ImageHashDefinition {
@@ -77,6 +79,9 @@ struct ImageHashDefinition {
typedef BOpenHashTable<ImageHashDefinition> ImageHash;
} // namespace
static ImageHash *sImagesHash;
static struct elf_image_info *sKernelImage = NULL;
+9 -5
View File
@@ -46,6 +46,8 @@
#endif
namespace {
struct rootfs_stream {
mode_t type;
struct stream_dir {
@@ -124,11 +126,13 @@ enum {
ITERATION_STATE_BEGIN = ITERATION_STATE_DOT,
};
// extern and in a private namespace only to make forward declaration possible
namespace {
extern fs_volume_ops sVolumeOps;
extern fs_vnode_ops sVnodeOps;
}
// extern only to make forward declaration possible
extern fs_volume_ops sVolumeOps;
extern fs_vnode_ops sVnodeOps;
} // namespace
#define ROOTFS_HASH_SIZE 16
+19 -6
View File
@@ -111,11 +111,6 @@ const static size_t kMaxPathLength = 65536;
// on PATH_MAX
struct vnode_hash_key {
dev_t device;
ino_t vnode;
};
typedef DoublyLinkedList<vnode> VnodeList;
/*! \brief Structure to manage a mounted file system
@@ -171,6 +166,9 @@ struct fs_mount {
bool owns_file_device;
};
namespace {
struct advisory_lock : public DoublyLinkedListLinkImpl<advisory_lock> {
list_link link;
team_id team;
@@ -182,6 +180,9 @@ struct advisory_lock : public DoublyLinkedListLinkImpl<advisory_lock> {
typedef DoublyLinkedList<advisory_lock> LockList;
} // namespace
struct advisory_locking {
sem_id lock;
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");
namespace {
struct vnode_hash_key {
dev_t device;
ino_t vnode;
};
struct VnodeHash {
typedef vnode_hash_key KeyType;
typedef struct vnode ValueType;
@@ -311,6 +319,8 @@ struct MountHash {
typedef BOpenHashTable<MountHash> MountTable;
} // namespace
#define VNODE_HASH_TABLE_SIZE 1024
static VnodeTable* sVnodeTable;
@@ -520,7 +530,8 @@ static struct fd_ops sQueryOps = {
};
// VNodePutter
namespace {
class VNodePutter {
public:
VNodePutter(struct vnode* vnode = NULL) : fVNode(vnode) {}
@@ -597,6 +608,8 @@ private:
bool fKernel;
};
} // namespace
#if VFS_PAGES_IO_TRACING
+4
View File
@@ -33,6 +33,8 @@
#define ADD_DEBUGGER_COMMANDS
namespace {
struct ImageTableDefinition {
typedef image_id KeyType;
typedef struct image ValueType;
@@ -68,6 +70,8 @@ public:
}
};
} // namespace
static image_id sNextImageID = 1;
static mutex sImageMutex = MUTEX_INITIALIZER("image");
+39 -39
View File
@@ -275,45 +275,6 @@ private:
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 {
typedef const char* KeyType;
@@ -364,6 +325,45 @@ struct ImageHash {
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
* 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.
struct port_message;
static void put_port_message(port_message* message);
namespace {
struct port_message : DoublyLinkedListLinkImpl<port_message> {
int32 code;
@@ -103,6 +99,13 @@ struct port_message : DoublyLinkedListLinkImpl<port_message> {
typedef DoublyLinkedList<port_message> MessageList;
} // namespace
static void put_port_message(port_message* message);
namespace {
struct Port : public KernelReferenceable {
enum State {
@@ -233,6 +236,8 @@ public:
void Notify(uint32 opcode, port_id team);
};
} // namespace
// #pragma mark - tracing
+4
View File
@@ -24,6 +24,8 @@
#include <util/StringHash.h>
namespace {
class SemInfo {
public:
SemInfo()
@@ -364,6 +366,8 @@ struct TeamSemHashDefinition {
}
};
} // namespace
struct realtime_sem_context {
realtime_sem_context()
@@ -33,6 +33,9 @@
# define TRACE_ERROR(x) dprintf x
#endif
namespace {
// Queue for holding blocked threads
struct queued_thread : DoublyLinkedListLinkImpl<queued_thread> {
queued_thread(Thread *_thread, int32 _message_length)
@@ -374,6 +377,9 @@ struct IpcHashTableDefinition {
}
};
} // namespace
// Arbitrary limits
#define MAX_XSI_MESSAGE 4096
#define MAX_XSI_MESSAGE_QUEUE 1024
+13
View File
@@ -34,6 +34,9 @@
# define TRACE_ERROR(x) dprintf x
#endif
namespace {
// Queue for holding blocked threads
struct queued_thread : DoublyLinkedListLinkImpl<queued_thread> {
queued_thread(Thread *thread, int32 count)
@@ -72,6 +75,10 @@ typedef DoublyLinkedList<sem_undo> UndoList;
typedef DoublyLinkedList<sem_undo,
DoublyLinkedListMemberGetLink<sem_undo, &sem_undo::team_link> > TeamList;
} // namespace
// Forward declared in global namespace.
struct xsi_sem_context {
xsi_sem_context()
{
@@ -87,6 +94,9 @@ struct xsi_sem_context {
mutex lock;
};
namespace {
// Xsi semaphore definition
class XsiSemaphore {
public:
@@ -621,6 +631,9 @@ struct IpcHashTableDefinition {
}
};
} // namespace
// Arbitrary limit
#define MAX_XSI_SEMAPHORE 4096
#define MAX_XSI_SEMAPHORE_SET 2048
+5
View File
@@ -42,6 +42,8 @@
// #pragma mark - AddressSpaceHashDefinition
namespace {
struct AddressSpaceHashDefinition {
typedef team_id KeyType;
typedef VMAddressSpace ValueType;
@@ -69,6 +71,9 @@ struct AddressSpaceHashDefinition {
typedef BOpenHashTable<AddressSpaceHashDefinition> AddressSpaceTable;
} // namespace
static AddressSpaceTable sAddressSpaceTable;
static rw_lock sAddressSpaceTableLock;
+4
View File
@@ -73,6 +73,8 @@
#endif
namespace {
class AreaCacheLocking {
public:
inline bool Lock(VMCache* lockable)
@@ -229,6 +231,8 @@ private:
VMCache* fBottomCache;
};
} // namespace
// The memory reserve an allocation of the certain priority must not touch.
static const size_t kMemoryReserveForPriority[] = {