A process (really, a "task") is a containment and management object that represents a running instance of a program. A program ("task") does not run, its threads do.
The significant difference between Windows-related OS kernels and Unix-y ones is that process creation is much more heavyweight on the former. Nevertheless, on both types of systems, it is threads that execute code and technically run.
However, from the application programmer's perspective, the convention on Unix-likes (which is what really matters) is to fork and pipe between processes as IPC, whereas on Windows this is not the case. Clearly the process start-up time on Unix-likes is considered fast enough that parallelism on Unix until fairly recently was based on spinning up tens to hundreds of processes and IPC-ing between them.
I believe the point stands.
But not for many other kinds of application programming, where you create threads using pthreads or some similar API, which are mapped 1:1 onto kernel threads that collectively form a "process".
I'm not sure what your definition of "fairly recently" is, but in the mid-90s, when we wanted to test new SMP systems, we would typically write code that used pthreads for parallelism. The fact that there is indeed a story about process-level parallelism (with IPC) in Unix-y systems should not distract from the equally fact existence and use of thread-level parallelism for at least 35 years.
A nice historical overview is…
https://developer.apple.com/library/archive/documentation/Da...
https://www.usenix.org/conference/usenix-mach-iii-symposium/...
Linux is the only Unix-like kernel I actually know anything about. In Linux, processes essentially do not exist. You have threads, and thread groups. A thread group is what most of the user-space tooling calls a process. It doesn't do very much by itself. As the name implies, it mostly just groups threads together under one identifier.
Linux threads and "processes" are both created using the "clone" system call, which allows the caller to specify how much state the new thread shares with the old thread. Share almost everything, and you have a "thread". Share almost nothing, and you have a "process". But the kernel treats them the same.
By contrast, processes in NT are real data structures that hold all kinds of attributes, none of which is a running piece of code, since that's still handled by a thread in both designs.
In contrast, Linux threads were implemented essentially as a hack - they were processes that shared memory and resources with their parent process, and were referred to internally as LWPs - lightweight processes.
I also remember a lot of Unix/Linux people not liking the idea of multithreading, preferring multiple processes to one, single-threaded process.
[1]https://en.wikipedia.org/wiki/LinuxThreads
[2]https://en.wikipedia.org/wiki/Native_POSIX_Thread_Library
This is amongst the most important and visible differences between NT and Unix-likes, really. The key idea is that processes manage threads. Pavel Yosifovich in Windows 10 System Internals Part I puts it succinctly:
NtCreateProcess is extremely expensive and its direct use strongly discouraged (but Cygwin and MSYS2, in their IMO misguided intention to force Unix paradigms onto Windows, wrote fork() anyway), but thread creation and management is extremely straightforward, and the Windows threading API is as a result much nicer than pthreads.