Content scripts run in the same process as the page/frame. All content scripts of this page/frame run in a single isolated JS environment. Each extension has its own such environment so its global variables/functions aren't visible to the page or other extensions and vice versa, their global types and prototypes like Array.prototype, DOM expandos, custom element methods, are isolated, too.
Web pages/frames use one process per site so all pages/frames of one site will run in the same process although Chrome and Firefox may group several sites in one process under memory pressure, AFAIK.
All pages of an extension have a chrome-extension:// URL and run in a single process. Each extension has its own process and it is never grouped with anything else in Chrome to lower the possibility of privilege escalation via bug exploits. Examples of such pages/entities are the background page, the background service worker, options page, action popup page, any html opened in a tab, or an iframe from web_accessible_resources which is often used to add UI of the extension to a web page. All these entities have a chrome-extension:// URL.
Doing a computationally heavy operation (technically "a single long task of JS event loop") in any of chrome-extension:// pages will block the entire extension process i.e. all pages/frames of this extension will be blocked. Not content scripts of course because they run in the web page process. Since JS is single-threaded per specification, the closest thing to a thread is a worker. It's relatively heavyweight compared to a thread in more capable languages but practically they are often called threads anyway and devtools uses this term, too. So even though workers aren't threads, they would still help with such computationally heavy tasks to free up the main extension process. One of the few good aspects of ManifestV3 switch from the background scripts to a service worker is that the latter won't be blocked in this case and vice versa: the service worker won't block the UI or scripts of extension pages.
chrome.runtime messaging (both port-based and one-time messaging) is using custom implementation, see the
source code. When the message needs to be sent across different processes it technically becomes IPC (inter-process communication), but it also can be used within the same process i.e. when the popup page sends a message to the background script or vice versa. Note that since it internally uses JSON.stringify/JSON.parse, it kills any nontrivial values like Set or Map. So, for same-process messaging between extension pages you may want to use the web platform API such as BroadcastChannel which utilizes the structured clone algorithm and thus is much faster (noticeable when the transferred data is a deeply nested object), it also supports many
complex types.